linux/drivers/i2c/busses/i2c-digicolor.c
<<
>>
Prefs
   1/*
   2 * I2C bus driver for Conexant Digicolor SoCs
   3 *
   4 * Author: Baruch Siach <baruch@tkos.co.il>
   5 *
   6 * Copyright (C) 2015 Paradox Innovation Ltd.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/completion.h>
  15#include <linux/delay.h>
  16#include <linux/i2c.h>
  17#include <linux/interrupt.h>
  18#include <linux/io.h>
  19#include <linux/kernel.h>
  20#include <linux/module.h>
  21#include <linux/of.h>
  22#include <linux/platform_device.h>
  23
  24#define DEFAULT_FREQ            100000
  25#define TIMEOUT_MS              100
  26
  27#define II_CONTROL              0x0
  28#define II_CONTROL_LOCAL_RESET  BIT(0)
  29
  30#define II_CLOCKTIME            0x1
  31
  32#define II_COMMAND              0x2
  33#define II_CMD_START            1
  34#define II_CMD_RESTART          2
  35#define II_CMD_SEND_ACK         3
  36#define II_CMD_GET_ACK          6
  37#define II_CMD_GET_NOACK        7
  38#define II_CMD_STOP             10
  39#define II_COMMAND_GO           BIT(7)
  40#define II_COMMAND_COMPLETION_STATUS(r) (((r) >> 5) & 3)
  41#define II_CMD_STATUS_NORMAL    0
  42#define II_CMD_STATUS_ACK_GOOD  1
  43#define II_CMD_STATUS_ACK_BAD   2
  44#define II_CMD_STATUS_ABORT     3
  45
  46#define II_DATA                 0x3
  47#define II_INTFLAG_CLEAR        0x8
  48#define II_INTENABLE            0xa
  49
  50struct dc_i2c {
  51        struct i2c_adapter      adap;
  52        struct device           *dev;
  53        void __iomem            *regs;
  54        struct clk              *clk;
  55        unsigned int            frequency;
  56
  57        struct i2c_msg          *msg;
  58        unsigned int            msgbuf_ptr;
  59        int                     last;
  60        spinlock_t              lock;
  61        struct completion       done;
  62        int                     state;
  63        int                     error;
  64};
  65
  66enum {
  67        STATE_IDLE,
  68        STATE_START,
  69        STATE_ADDR,
  70        STATE_WRITE,
  71        STATE_READ,
  72        STATE_STOP,
  73};
  74
  75static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd)
  76{
  77        writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND);
  78}
  79
  80static u8 dc_i2c_addr_cmd(struct i2c_msg *msg)
  81{
  82        u8 addr = (msg->addr & 0x7f) << 1;
  83
  84        if (msg->flags & I2C_M_RD)
  85                addr |= 1;
  86
  87        return addr;
  88}
  89
  90static void dc_i2c_data(struct dc_i2c *i2c, u8 data)
  91{
  92        writeb_relaxed(data, i2c->regs + II_DATA);
  93}
  94
  95static void dc_i2c_write_byte(struct dc_i2c *i2c, u8 byte)
  96{
  97        dc_i2c_data(i2c, byte);
  98        dc_i2c_cmd(i2c, II_CMD_SEND_ACK);
  99}
 100
 101static void dc_i2c_write_buf(struct dc_i2c *i2c)
 102{
 103        dc_i2c_write_byte(i2c, i2c->msg->buf[i2c->msgbuf_ptr++]);
 104}
 105
 106static void dc_i2c_next_read(struct dc_i2c *i2c)
 107{
 108        bool last = (i2c->msgbuf_ptr + 1 == i2c->msg->len);
 109
 110        dc_i2c_cmd(i2c, last ? II_CMD_GET_NOACK : II_CMD_GET_ACK);
 111}
 112
 113static void dc_i2c_stop(struct dc_i2c *i2c)
 114{
 115        i2c->state = STATE_STOP;
 116        if (i2c->last)
 117                dc_i2c_cmd(i2c, II_CMD_STOP);
 118        else
 119                complete(&i2c->done);
 120}
 121
 122static u8 dc_i2c_read_byte(struct dc_i2c *i2c)
 123{
 124        return readb_relaxed(i2c->regs + II_DATA);
 125}
 126
 127static void dc_i2c_read_buf(struct dc_i2c *i2c)
 128{
 129        i2c->msg->buf[i2c->msgbuf_ptr++] = dc_i2c_read_byte(i2c);
 130        dc_i2c_next_read(i2c);
 131}
 132
 133static void dc_i2c_set_irq(struct dc_i2c *i2c, int enable)
 134{
 135        if (enable)
 136                writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
 137        writeb_relaxed(!!enable, i2c->regs + II_INTENABLE);
 138}
 139
 140static int dc_i2c_cmd_status(struct dc_i2c *i2c)
 141{
 142        u8 cmd = readb_relaxed(i2c->regs + II_COMMAND);
 143
 144        return II_COMMAND_COMPLETION_STATUS(cmd);
 145}
 146
 147static void dc_i2c_start_msg(struct dc_i2c *i2c, int first)
 148{
 149        struct i2c_msg *msg = i2c->msg;
 150
 151        if (!(msg->flags & I2C_M_NOSTART)) {
 152                i2c->state = STATE_START;
 153                dc_i2c_cmd(i2c, first ? II_CMD_START : II_CMD_RESTART);
 154        } else if (msg->flags & I2C_M_RD) {
 155                i2c->state = STATE_READ;
 156                dc_i2c_next_read(i2c);
 157        } else {
 158                i2c->state = STATE_WRITE;
 159                dc_i2c_write_buf(i2c);
 160        }
 161}
 162
 163static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
 164{
 165        struct dc_i2c *i2c = dev_id;
 166        int cmd_status = dc_i2c_cmd_status(i2c);
 167        unsigned long flags;
 168        u8 addr_cmd;
 169
 170        writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
 171
 172        spin_lock_irqsave(&i2c->lock, flags);
 173
 174        if (cmd_status == II_CMD_STATUS_ACK_BAD
 175            || cmd_status == II_CMD_STATUS_ABORT) {
 176                i2c->error = -EIO;
 177                complete(&i2c->done);
 178                goto out;
 179        }
 180
 181        switch (i2c->state) {
 182        case STATE_START:
 183                addr_cmd = dc_i2c_addr_cmd(i2c->msg);
 184                dc_i2c_write_byte(i2c, addr_cmd);
 185                i2c->state = STATE_ADDR;
 186                break;
 187        case STATE_ADDR:
 188                if (i2c->msg->flags & I2C_M_RD) {
 189                        dc_i2c_next_read(i2c);
 190                        i2c->state = STATE_READ;
 191                        break;
 192                }
 193                i2c->state = STATE_WRITE;
 194                /* fall through */
 195        case STATE_WRITE:
 196                if (i2c->msgbuf_ptr < i2c->msg->len)
 197                        dc_i2c_write_buf(i2c);
 198                else
 199                        dc_i2c_stop(i2c);
 200                break;
 201        case STATE_READ:
 202                if (i2c->msgbuf_ptr < i2c->msg->len)
 203                        dc_i2c_read_buf(i2c);
 204                else
 205                        dc_i2c_stop(i2c);
 206                break;
 207        case STATE_STOP:
 208                i2c->state = STATE_IDLE;
 209                complete(&i2c->done);
 210                break;
 211        }
 212
 213out:
 214        spin_unlock_irqrestore(&i2c->lock, flags);
 215        return IRQ_HANDLED;
 216}
 217
 218static int dc_i2c_xfer_msg(struct dc_i2c *i2c, struct i2c_msg *msg, int first,
 219                           int last)
 220{
 221        unsigned long timeout = msecs_to_jiffies(TIMEOUT_MS);
 222        unsigned long flags;
 223
 224        spin_lock_irqsave(&i2c->lock, flags);
 225        i2c->msg = msg;
 226        i2c->msgbuf_ptr = 0;
 227        i2c->last = last;
 228        i2c->error = 0;
 229
 230        reinit_completion(&i2c->done);
 231        dc_i2c_set_irq(i2c, 1);
 232        dc_i2c_start_msg(i2c, first);
 233        spin_unlock_irqrestore(&i2c->lock, flags);
 234
 235        timeout = wait_for_completion_timeout(&i2c->done, timeout);
 236        dc_i2c_set_irq(i2c, 0);
 237        if (timeout == 0) {
 238                i2c->state = STATE_IDLE;
 239                return -ETIMEDOUT;
 240        }
 241
 242        if (i2c->error)
 243                return i2c->error;
 244
 245        return 0;
 246}
 247
 248static int dc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 249{
 250        struct dc_i2c *i2c = adap->algo_data;
 251        int i, ret;
 252
 253        for (i = 0; i < num; i++) {
 254                ret = dc_i2c_xfer_msg(i2c, &msgs[i], i == 0, i == num - 1);
 255                if (ret)
 256                        return ret;
 257        }
 258
 259        return num;
 260}
 261
 262static int dc_i2c_init_hw(struct dc_i2c *i2c)
 263{
 264        unsigned long clk_rate = clk_get_rate(i2c->clk);
 265        unsigned int clocktime;
 266
 267        writeb_relaxed(II_CONTROL_LOCAL_RESET, i2c->regs + II_CONTROL);
 268        udelay(100);
 269        writeb_relaxed(0, i2c->regs + II_CONTROL);
 270        udelay(100);
 271
 272        clocktime = DIV_ROUND_UP(clk_rate, 64 * i2c->frequency);
 273        if (clocktime < 1 || clocktime > 0xff) {
 274                dev_err(i2c->dev, "can't set bus speed of %u Hz\n",
 275                        i2c->frequency);
 276                return -EINVAL;
 277        }
 278        writeb_relaxed(clocktime - 1, i2c->regs + II_CLOCKTIME);
 279
 280        return 0;
 281}
 282
 283static u32 dc_i2c_func(struct i2c_adapter *adap)
 284{
 285        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
 286}
 287
 288static const struct i2c_algorithm dc_i2c_algorithm = {
 289        .master_xfer    = dc_i2c_xfer,
 290        .functionality  = dc_i2c_func,
 291};
 292
 293static int dc_i2c_probe(struct platform_device *pdev)
 294{
 295        struct device_node *np = pdev->dev.of_node;
 296        struct dc_i2c *i2c;
 297        struct resource *r;
 298        int ret = 0, irq;
 299
 300        i2c = devm_kzalloc(&pdev->dev, sizeof(struct dc_i2c), GFP_KERNEL);
 301        if (!i2c)
 302                return -ENOMEM;
 303
 304        if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
 305                                 &i2c->frequency))
 306                i2c->frequency = DEFAULT_FREQ;
 307
 308        i2c->dev = &pdev->dev;
 309        platform_set_drvdata(pdev, i2c);
 310
 311        spin_lock_init(&i2c->lock);
 312        init_completion(&i2c->done);
 313
 314        i2c->clk = devm_clk_get(&pdev->dev, NULL);
 315        if (IS_ERR(i2c->clk))
 316                return PTR_ERR(i2c->clk);
 317
 318        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 319        i2c->regs = devm_ioremap_resource(&pdev->dev, r);
 320        if (IS_ERR(i2c->regs))
 321                return PTR_ERR(i2c->regs);
 322
 323        irq = platform_get_irq(pdev, 0);
 324        if (irq < 0)
 325                return irq;
 326
 327        ret = devm_request_irq(&pdev->dev, irq, dc_i2c_irq, 0,
 328                               dev_name(&pdev->dev), i2c);
 329        if (ret < 0)
 330                return ret;
 331
 332        strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter",
 333                sizeof(i2c->adap.name));
 334        i2c->adap.owner = THIS_MODULE;
 335        i2c->adap.algo = &dc_i2c_algorithm;
 336        i2c->adap.dev.parent = &pdev->dev;
 337        i2c->adap.dev.of_node = np;
 338        i2c->adap.algo_data = i2c;
 339
 340        ret = dc_i2c_init_hw(i2c);
 341        if (ret)
 342                return ret;
 343
 344        ret = clk_prepare_enable(i2c->clk);
 345        if (ret < 0)
 346                return ret;
 347
 348        ret = i2c_add_adapter(&i2c->adap);
 349        if (ret < 0) {
 350                clk_disable_unprepare(i2c->clk);
 351                return ret;
 352        }
 353
 354        return 0;
 355}
 356
 357static int dc_i2c_remove(struct platform_device *pdev)
 358{
 359        struct dc_i2c *i2c = platform_get_drvdata(pdev);
 360
 361        i2c_del_adapter(&i2c->adap);
 362        clk_disable_unprepare(i2c->clk);
 363
 364        return 0;
 365}
 366
 367static const struct of_device_id dc_i2c_match[] = {
 368        { .compatible = "cnxt,cx92755-i2c" },
 369        { },
 370};
 371MODULE_DEVICE_TABLE(of, dc_i2c_match);
 372
 373static struct platform_driver dc_i2c_driver = {
 374        .probe   = dc_i2c_probe,
 375        .remove  = dc_i2c_remove,
 376        .driver  = {
 377                .name  = "digicolor-i2c",
 378                .of_match_table = dc_i2c_match,
 379        },
 380};
 381module_platform_driver(dc_i2c_driver);
 382
 383MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
 384MODULE_DESCRIPTION("Conexant Digicolor I2C master driver");
 385MODULE_LICENSE("GPL v2");
 386