linux/drivers/i2c/busses/i2c-meson.c
<<
>>
Prefs
   1/*
   2 * I2C bus driver for Amlogic Meson SoCs
   3 *
   4 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/completion.h>
  13#include <linux/i2c.h>
  14#include <linux/interrupt.h>
  15#include <linux/io.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/platform_device.h>
  20#include <linux/types.h>
  21
  22/* Meson I2C register map */
  23#define REG_CTRL                0x00
  24#define REG_SLAVE_ADDR          0x04
  25#define REG_TOK_LIST0           0x08
  26#define REG_TOK_LIST1           0x0c
  27#define REG_TOK_WDATA0          0x10
  28#define REG_TOK_WDATA1          0x14
  29#define REG_TOK_RDATA0          0x18
  30#define REG_TOK_RDATA1          0x1c
  31
  32/* Control register fields */
  33#define REG_CTRL_START          BIT(0)
  34#define REG_CTRL_ACK_IGNORE     BIT(1)
  35#define REG_CTRL_STATUS         BIT(2)
  36#define REG_CTRL_ERROR          BIT(3)
  37#define REG_CTRL_CLKDIV_SHIFT   12
  38#define REG_CTRL_CLKDIV_MASK    ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
  39
  40#define I2C_TIMEOUT_MS          500
  41#define DEFAULT_FREQ            100000
  42
  43enum {
  44        TOKEN_END = 0,
  45        TOKEN_START,
  46        TOKEN_SLAVE_ADDR_WRITE,
  47        TOKEN_SLAVE_ADDR_READ,
  48        TOKEN_DATA,
  49        TOKEN_DATA_LAST,
  50        TOKEN_STOP,
  51};
  52
  53enum {
  54        STATE_IDLE,
  55        STATE_READ,
  56        STATE_WRITE,
  57        STATE_STOP,
  58};
  59
  60/**
  61 * struct meson_i2c - Meson I2C device private data
  62 *
  63 * @adap:       I2C adapter instance
  64 * @dev:        Pointer to device structure
  65 * @regs:       Base address of the device memory mapped registers
  66 * @clk:        Pointer to clock structure
  67 * @irq:        IRQ number
  68 * @msg:        Pointer to the current I2C message
  69 * @state:      Current state in the driver state machine
  70 * @last:       Flag set for the last message in the transfer
  71 * @count:      Number of bytes to be sent/received in current transfer
  72 * @pos:        Current position in the send/receive buffer
  73 * @error:      Flag set when an error is received
  74 * @lock:       To avoid race conditions between irq handler and xfer code
  75 * @done:       Completion used to wait for transfer termination
  76 * @frequency:  Operating frequency of I2C bus clock
  77 * @tokens:     Sequence of tokens to be written to the device
  78 * @num_tokens: Number of tokens
  79 */
  80struct meson_i2c {
  81        struct i2c_adapter      adap;
  82        struct device           *dev;
  83        void __iomem            *regs;
  84        struct clk              *clk;
  85        int                     irq;
  86
  87        struct i2c_msg          *msg;
  88        int                     state;
  89        bool                    last;
  90        int                     count;
  91        int                     pos;
  92        int                     error;
  93
  94        spinlock_t              lock;
  95        struct completion       done;
  96        unsigned int            frequency;
  97        u32                     tokens[2];
  98        int                     num_tokens;
  99};
 100
 101static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask,
 102                               u32 val)
 103{
 104        u32 data;
 105
 106        data = readl(i2c->regs + reg);
 107        data &= ~mask;
 108        data |= val & mask;
 109        writel(data, i2c->regs + reg);
 110}
 111
 112static void meson_i2c_reset_tokens(struct meson_i2c *i2c)
 113{
 114        i2c->tokens[0] = 0;
 115        i2c->tokens[1] = 0;
 116        i2c->num_tokens = 0;
 117}
 118
 119static void meson_i2c_add_token(struct meson_i2c *i2c, int token)
 120{
 121        if (i2c->num_tokens < 8)
 122                i2c->tokens[0] |= (token & 0xf) << (i2c->num_tokens * 4);
 123        else
 124                i2c->tokens[1] |= (token & 0xf) << ((i2c->num_tokens % 8) * 4);
 125
 126        i2c->num_tokens++;
 127}
 128
 129static void meson_i2c_write_tokens(struct meson_i2c *i2c)
 130{
 131        writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
 132        writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
 133}
 134
 135static void meson_i2c_set_clk_div(struct meson_i2c *i2c)
 136{
 137        unsigned long clk_rate = clk_get_rate(i2c->clk);
 138        unsigned int div;
 139
 140        div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4);
 141        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
 142                           div << REG_CTRL_CLKDIV_SHIFT);
 143
 144        dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
 145                clk_rate, i2c->frequency, div);
 146}
 147
 148static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
 149{
 150        u32 rdata0, rdata1;
 151        int i;
 152
 153        rdata0 = readl(i2c->regs + REG_TOK_RDATA0);
 154        rdata1 = readl(i2c->regs + REG_TOK_RDATA1);
 155
 156        dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
 157                rdata0, rdata1, len);
 158
 159        for (i = 0; i < min_t(int, 4, len); i++)
 160                *buf++ = (rdata0 >> i * 8) & 0xff;
 161
 162        for (i = 4; i < min_t(int, 8, len); i++)
 163                *buf++ = (rdata1 >> (i - 4) * 8) & 0xff;
 164}
 165
 166static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len)
 167{
 168        u32 wdata0 = 0, wdata1 = 0;
 169        int i;
 170
 171        for (i = 0; i < min_t(int, 4, len); i++)
 172                wdata0 |= *buf++ << (i * 8);
 173
 174        for (i = 4; i < min_t(int, 8, len); i++)
 175                wdata1 |= *buf++ << ((i - 4) * 8);
 176
 177        writel(wdata0, i2c->regs + REG_TOK_WDATA0);
 178        writel(wdata0, i2c->regs + REG_TOK_WDATA1);
 179
 180        dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
 181                wdata0, wdata1, len);
 182}
 183
 184static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
 185{
 186        bool write = !(i2c->msg->flags & I2C_M_RD);
 187        int i;
 188
 189        i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8);
 190
 191        for (i = 0; i < i2c->count - 1; i++)
 192                meson_i2c_add_token(i2c, TOKEN_DATA);
 193
 194        if (i2c->count) {
 195                if (write || i2c->pos + i2c->count < i2c->msg->len)
 196                        meson_i2c_add_token(i2c, TOKEN_DATA);
 197                else
 198                        meson_i2c_add_token(i2c, TOKEN_DATA_LAST);
 199        }
 200
 201        if (write)
 202                meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
 203}
 204
 205static void meson_i2c_stop(struct meson_i2c *i2c)
 206{
 207        dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last);
 208
 209        if (i2c->last) {
 210                i2c->state = STATE_STOP;
 211                meson_i2c_add_token(i2c, TOKEN_STOP);
 212        } else {
 213                i2c->state = STATE_IDLE;
 214                complete(&i2c->done);
 215        }
 216}
 217
 218static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
 219{
 220        struct meson_i2c *i2c = dev_id;
 221        unsigned int ctrl;
 222
 223        spin_lock(&i2c->lock);
 224
 225        meson_i2c_reset_tokens(i2c);
 226        ctrl = readl(i2c->regs + REG_CTRL);
 227
 228        dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n",
 229                i2c->state, i2c->pos, i2c->count, ctrl);
 230
 231        if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) {
 232                /*
 233                 * The bit is set when the IGNORE_NAK bit is cleared
 234                 * and the device didn't respond. In this case, the
 235                 * I2C controller automatically generates a STOP
 236                 * condition.
 237                 */
 238                dev_dbg(i2c->dev, "error bit set\n");
 239                i2c->error = -ENXIO;
 240                i2c->state = STATE_IDLE;
 241                complete(&i2c->done);
 242                goto out;
 243        }
 244
 245        switch (i2c->state) {
 246        case STATE_READ:
 247                if (i2c->count > 0) {
 248                        meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos,
 249                                           i2c->count);
 250                        i2c->pos += i2c->count;
 251                }
 252
 253                if (i2c->pos >= i2c->msg->len) {
 254                        meson_i2c_stop(i2c);
 255                        break;
 256                }
 257
 258                meson_i2c_prepare_xfer(i2c);
 259                break;
 260        case STATE_WRITE:
 261                i2c->pos += i2c->count;
 262
 263                if (i2c->pos >= i2c->msg->len) {
 264                        meson_i2c_stop(i2c);
 265                        break;
 266                }
 267
 268                meson_i2c_prepare_xfer(i2c);
 269                break;
 270        case STATE_STOP:
 271                i2c->state = STATE_IDLE;
 272                complete(&i2c->done);
 273                break;
 274        case STATE_IDLE:
 275                break;
 276        }
 277
 278out:
 279        if (i2c->state != STATE_IDLE) {
 280                /* Restart the processing */
 281                meson_i2c_write_tokens(i2c);
 282                meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
 283                meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
 284                                   REG_CTRL_START);
 285        }
 286
 287        spin_unlock(&i2c->lock);
 288
 289        return IRQ_HANDLED;
 290}
 291
 292static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
 293{
 294        int token;
 295
 296        token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ :
 297                TOKEN_SLAVE_ADDR_WRITE;
 298
 299        writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR);
 300        meson_i2c_add_token(i2c, TOKEN_START);
 301        meson_i2c_add_token(i2c, token);
 302}
 303
 304static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg,
 305                              int last)
 306{
 307        unsigned long time_left, flags;
 308        int ret = 0;
 309
 310        i2c->msg = msg;
 311        i2c->last = last;
 312        i2c->pos = 0;
 313        i2c->count = 0;
 314        i2c->error = 0;
 315
 316        meson_i2c_reset_tokens(i2c);
 317
 318        flags = (msg->flags & I2C_M_IGNORE_NAK) ? REG_CTRL_ACK_IGNORE : 0;
 319        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_ACK_IGNORE, flags);
 320
 321        if (!(msg->flags & I2C_M_NOSTART))
 322                meson_i2c_do_start(i2c, msg);
 323
 324        i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
 325        meson_i2c_prepare_xfer(i2c);
 326        meson_i2c_write_tokens(i2c);
 327        reinit_completion(&i2c->done);
 328
 329        /* Start the transfer */
 330        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START);
 331
 332        time_left = msecs_to_jiffies(I2C_TIMEOUT_MS);
 333        time_left = wait_for_completion_timeout(&i2c->done, time_left);
 334
 335        /*
 336         * Protect access to i2c struct and registers from interrupt
 337         * handlers triggered by a transfer terminated after the
 338         * timeout period
 339         */
 340        spin_lock_irqsave(&i2c->lock, flags);
 341
 342        /* Abort any active operation */
 343        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
 344
 345        if (!time_left) {
 346                i2c->state = STATE_IDLE;
 347                ret = -ETIMEDOUT;
 348        }
 349
 350        if (i2c->error)
 351                ret = i2c->error;
 352
 353        spin_unlock_irqrestore(&i2c->lock, flags);
 354
 355        return ret;
 356}
 357
 358static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 359                          int num)
 360{
 361        struct meson_i2c *i2c = adap->algo_data;
 362        int i, ret = 0, count = 0;
 363
 364        clk_enable(i2c->clk);
 365        meson_i2c_set_clk_div(i2c);
 366
 367        for (i = 0; i < num; i++) {
 368                ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1);
 369                if (ret)
 370                        break;
 371                count++;
 372        }
 373
 374        clk_disable(i2c->clk);
 375
 376        return ret ? ret : count;
 377}
 378
 379static u32 meson_i2c_func(struct i2c_adapter *adap)
 380{
 381        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 382}
 383
 384static const struct i2c_algorithm meson_i2c_algorithm = {
 385        .master_xfer    = meson_i2c_xfer,
 386        .functionality  = meson_i2c_func,
 387};
 388
 389static int meson_i2c_probe(struct platform_device *pdev)
 390{
 391        struct device_node *np = pdev->dev.of_node;
 392        struct meson_i2c *i2c;
 393        struct resource *mem;
 394        int ret = 0;
 395
 396        i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
 397        if (!i2c)
 398                return -ENOMEM;
 399
 400        if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
 401                                 &i2c->frequency))
 402                i2c->frequency = DEFAULT_FREQ;
 403
 404        i2c->dev = &pdev->dev;
 405        platform_set_drvdata(pdev, i2c);
 406
 407        spin_lock_init(&i2c->lock);
 408        init_completion(&i2c->done);
 409
 410        i2c->clk = devm_clk_get(&pdev->dev, NULL);
 411        if (IS_ERR(i2c->clk)) {
 412                dev_err(&pdev->dev, "can't get device clock\n");
 413                return PTR_ERR(i2c->clk);
 414        }
 415
 416        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 417        i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
 418        if (IS_ERR(i2c->regs))
 419                return PTR_ERR(i2c->regs);
 420
 421        i2c->irq = platform_get_irq(pdev, 0);
 422        if (i2c->irq < 0) {
 423                dev_err(&pdev->dev, "can't find IRQ\n");
 424                return i2c->irq;
 425        }
 426
 427        ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq,
 428                               0, dev_name(&pdev->dev), i2c);
 429        if (ret < 0) {
 430                dev_err(&pdev->dev, "can't request IRQ\n");
 431                return ret;
 432        }
 433
 434        ret = clk_prepare(i2c->clk);
 435        if (ret < 0) {
 436                dev_err(&pdev->dev, "can't prepare clock\n");
 437                return ret;
 438        }
 439
 440        strlcpy(i2c->adap.name, "Meson I2C adapter",
 441                sizeof(i2c->adap.name));
 442        i2c->adap.owner = THIS_MODULE;
 443        i2c->adap.algo = &meson_i2c_algorithm;
 444        i2c->adap.dev.parent = &pdev->dev;
 445        i2c->adap.dev.of_node = np;
 446        i2c->adap.algo_data = i2c;
 447
 448        /*
 449         * A transfer is triggered when START bit changes from 0 to 1.
 450         * Ensure that the bit is set to 0 after probe
 451         */
 452        meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
 453
 454        ret = i2c_add_adapter(&i2c->adap);
 455        if (ret < 0) {
 456                clk_unprepare(i2c->clk);
 457                return ret;
 458        }
 459
 460        return 0;
 461}
 462
 463static int meson_i2c_remove(struct platform_device *pdev)
 464{
 465        struct meson_i2c *i2c = platform_get_drvdata(pdev);
 466
 467        i2c_del_adapter(&i2c->adap);
 468        clk_unprepare(i2c->clk);
 469
 470        return 0;
 471}
 472
 473static const struct of_device_id meson_i2c_match[] = {
 474        { .compatible = "amlogic,meson6-i2c" },
 475        { .compatible = "amlogic,meson-gxbb-i2c" },
 476        { },
 477};
 478MODULE_DEVICE_TABLE(of, meson_i2c_match);
 479
 480static struct platform_driver meson_i2c_driver = {
 481        .probe   = meson_i2c_probe,
 482        .remove  = meson_i2c_remove,
 483        .driver  = {
 484                .name  = "meson-i2c",
 485                .of_match_table = meson_i2c_match,
 486        },
 487};
 488
 489module_platform_driver(meson_i2c_driver);
 490
 491MODULE_DESCRIPTION("Amlogic Meson I2C Bus driver");
 492MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 493MODULE_LICENSE("GPL v2");
 494