linux/drivers/media/pci/cx25821/cx25821-i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Driver for the Conexant CX25821 PCIe bridge
   4 *
   5 *  Copyright (C) 2009 Conexant Systems Inc.
   6 *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
   7 *      Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/module.h>
  13#include <linux/i2c.h>
  14#include "cx25821.h"
  15
  16static unsigned int i2c_debug;
  17module_param(i2c_debug, int, 0644);
  18MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
  19
  20static unsigned int i2c_scan;
  21module_param(i2c_scan, int, 0444);
  22MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
  23
  24#define dprintk(level, fmt, arg...)                                     \
  25do {                                                                    \
  26        if (i2c_debug >= level)                                         \
  27                printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);      \
  28} while (0)
  29
  30#define I2C_WAIT_DELAY 32
  31#define I2C_WAIT_RETRY 64
  32
  33#define I2C_EXTEND  (1 << 3)
  34#define I2C_NOSTOP  (1 << 4)
  35
  36static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
  37{
  38        struct cx25821_i2c *bus = i2c_adap->algo_data;
  39        struct cx25821_dev *dev = bus->dev;
  40        return cx_read(bus->reg_stat) & 0x01;
  41}
  42
  43static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
  44{
  45        struct cx25821_i2c *bus = i2c_adap->algo_data;
  46        struct cx25821_dev *dev = bus->dev;
  47        return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
  48}
  49
  50static int i2c_wait_done(struct i2c_adapter *i2c_adap)
  51{
  52        int count;
  53
  54        for (count = 0; count < I2C_WAIT_RETRY; count++) {
  55                if (!i2c_is_busy(i2c_adap))
  56                        break;
  57                udelay(I2C_WAIT_DELAY);
  58        }
  59
  60        if (I2C_WAIT_RETRY == count)
  61                return 0;
  62
  63        return 1;
  64}
  65
  66static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
  67                         const struct i2c_msg *msg, int joined_rlen)
  68{
  69        struct cx25821_i2c *bus = i2c_adap->algo_data;
  70        struct cx25821_dev *dev = bus->dev;
  71        u32 wdata, addr, ctrl;
  72        int retval, cnt;
  73
  74        if (joined_rlen)
  75                dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
  76                        msg->len, joined_rlen);
  77        else
  78                dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
  79
  80        /* Deal with i2c probe functions with zero payload */
  81        if (msg->len == 0) {
  82                cx_write(bus->reg_addr, msg->addr << 25);
  83                cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
  84
  85                if (!i2c_wait_done(i2c_adap))
  86                        return -EIO;
  87
  88                if (!i2c_slave_did_ack(i2c_adap))
  89                        return -EIO;
  90
  91                dprintk(1, "%s(): returns 0\n", __func__);
  92                return 0;
  93        }
  94
  95        /* dev, reg + first byte */
  96        addr = (msg->addr << 25) | msg->buf[0];
  97        wdata = msg->buf[0];
  98
  99        ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
 100
 101        if (msg->len > 1)
 102                ctrl |= I2C_NOSTOP | I2C_EXTEND;
 103        else if (joined_rlen)
 104                ctrl |= I2C_NOSTOP;
 105
 106        cx_write(bus->reg_addr, addr);
 107        cx_write(bus->reg_wdata, wdata);
 108        cx_write(bus->reg_ctrl, ctrl);
 109
 110        retval = i2c_wait_done(i2c_adap);
 111        if (retval < 0)
 112                goto err;
 113
 114        if (retval == 0)
 115                goto eio;
 116
 117        if (i2c_debug) {
 118                if (!(ctrl & I2C_NOSTOP))
 119                        printk(" >\n");
 120        }
 121
 122        for (cnt = 1; cnt < msg->len; cnt++) {
 123                /* following bytes */
 124                wdata = msg->buf[cnt];
 125                ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
 126
 127                if (cnt < msg->len - 1)
 128                        ctrl |= I2C_NOSTOP | I2C_EXTEND;
 129                else if (joined_rlen)
 130                        ctrl |= I2C_NOSTOP;
 131
 132                cx_write(bus->reg_addr, addr);
 133                cx_write(bus->reg_wdata, wdata);
 134                cx_write(bus->reg_ctrl, ctrl);
 135
 136                retval = i2c_wait_done(i2c_adap);
 137                if (retval < 0)
 138                        goto err;
 139
 140                if (retval == 0)
 141                        goto eio;
 142
 143                if (i2c_debug) {
 144                        dprintk(1, " %02x", msg->buf[cnt]);
 145                        if (!(ctrl & I2C_NOSTOP))
 146                                dprintk(1, " >\n");
 147                }
 148        }
 149
 150        return msg->len;
 151
 152eio:
 153        retval = -EIO;
 154err:
 155        if (i2c_debug)
 156                pr_err(" ERR: %d\n", retval);
 157        return retval;
 158}
 159
 160static int i2c_readbytes(struct i2c_adapter *i2c_adap,
 161                         const struct i2c_msg *msg, int joined)
 162{
 163        struct cx25821_i2c *bus = i2c_adap->algo_data;
 164        struct cx25821_dev *dev = bus->dev;
 165        u32 ctrl, cnt;
 166        int retval;
 167
 168        if (i2c_debug && !joined)
 169                dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
 170
 171        /* Deal with i2c probe functions with zero payload */
 172        if (msg->len == 0) {
 173                cx_write(bus->reg_addr, msg->addr << 25);
 174                cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
 175                if (!i2c_wait_done(i2c_adap))
 176                        return -EIO;
 177                if (!i2c_slave_did_ack(i2c_adap))
 178                        return -EIO;
 179
 180                dprintk(1, "%s(): returns 0\n", __func__);
 181                return 0;
 182        }
 183
 184        if (i2c_debug) {
 185                if (joined)
 186                        dprintk(1, " R");
 187                else
 188                        dprintk(1, " <R %02x", (msg->addr << 1) + 1);
 189        }
 190
 191        for (cnt = 0; cnt < msg->len; cnt++) {
 192
 193                ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
 194
 195                if (cnt < msg->len - 1)
 196                        ctrl |= I2C_NOSTOP | I2C_EXTEND;
 197
 198                cx_write(bus->reg_addr, msg->addr << 25);
 199                cx_write(bus->reg_ctrl, ctrl);
 200
 201                retval = i2c_wait_done(i2c_adap);
 202                if (retval < 0)
 203                        goto err;
 204                if (retval == 0)
 205                        goto eio;
 206                msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
 207
 208                if (i2c_debug) {
 209                        dprintk(1, " %02x", msg->buf[cnt]);
 210                        if (!(ctrl & I2C_NOSTOP))
 211                                dprintk(1, " >\n");
 212                }
 213        }
 214
 215        return msg->len;
 216eio:
 217        retval = -EIO;
 218err:
 219        if (i2c_debug)
 220                pr_err(" ERR: %d\n", retval);
 221        return retval;
 222}
 223
 224static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 225{
 226        struct cx25821_i2c *bus = i2c_adap->algo_data;
 227        struct cx25821_dev *dev = bus->dev;
 228        int i, retval = 0;
 229
 230        dprintk(1, "%s(num = %d)\n", __func__, num);
 231
 232        for (i = 0; i < num; i++) {
 233                dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
 234                        __func__, num, msgs[i].addr, msgs[i].len);
 235
 236                if (msgs[i].flags & I2C_M_RD) {
 237                        /* read */
 238                        retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
 239                } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
 240                           msgs[i].addr == msgs[i + 1].addr) {
 241                        /* write then read from same address */
 242                        retval = i2c_sendbytes(i2c_adap, &msgs[i],
 243                                        msgs[i + 1].len);
 244
 245                        if (retval < 0)
 246                                goto err;
 247                        i++;
 248                        retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
 249                } else {
 250                        /* write */
 251                        retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
 252                }
 253
 254                if (retval < 0)
 255                        goto err;
 256        }
 257        return num;
 258
 259err:
 260        return retval;
 261}
 262
 263
 264static u32 cx25821_functionality(struct i2c_adapter *adap)
 265{
 266        return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
 267                I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
 268}
 269
 270static const struct i2c_algorithm cx25821_i2c_algo_template = {
 271        .master_xfer = i2c_xfer,
 272        .functionality = cx25821_functionality,
 273#ifdef NEED_ALGO_CONTROL
 274        .algo_control = dummy_algo_control,
 275#endif
 276};
 277
 278static const struct i2c_adapter cx25821_i2c_adap_template = {
 279        .name = "cx25821",
 280        .owner = THIS_MODULE,
 281        .algo = &cx25821_i2c_algo_template,
 282};
 283
 284static const struct i2c_client cx25821_i2c_client_template = {
 285        .name = "cx25821 internal",
 286};
 287
 288/* init + register i2c adapter */
 289int cx25821_i2c_register(struct cx25821_i2c *bus)
 290{
 291        struct cx25821_dev *dev = bus->dev;
 292
 293        dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
 294
 295        bus->i2c_adap = cx25821_i2c_adap_template;
 296        bus->i2c_client = cx25821_i2c_client_template;
 297        bus->i2c_adap.dev.parent = &dev->pci->dev;
 298
 299        strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
 300
 301        bus->i2c_adap.algo_data = bus;
 302        i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
 303        i2c_add_adapter(&bus->i2c_adap);
 304
 305        bus->i2c_client.adapter = &bus->i2c_adap;
 306
 307        /* set up the I2c */
 308        bus->i2c_client.addr = (0x88 >> 1);
 309
 310        return bus->i2c_rc;
 311}
 312
 313int cx25821_i2c_unregister(struct cx25821_i2c *bus)
 314{
 315        i2c_del_adapter(&bus->i2c_adap);
 316        return 0;
 317}
 318
 319#if 0 /* Currently unused */
 320static void cx25821_av_clk(struct cx25821_dev *dev, int enable)
 321{
 322        /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
 323        char buffer[3];
 324        struct i2c_msg msg;
 325        dprintk(1, "%s(enabled = %d)\n", __func__, enable);
 326
 327        /* Register 0x144 */
 328        buffer[0] = 0x01;
 329        buffer[1] = 0x44;
 330        if (enable == 1)
 331                buffer[2] = 0x05;
 332        else
 333                buffer[2] = 0x00;
 334
 335        msg.addr = 0x44;
 336        msg.flags = I2C_M_TEN;
 337        msg.len = 3;
 338        msg.buf = buffer;
 339
 340        i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
 341}
 342#endif
 343
 344int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
 345{
 346        struct i2c_client *client = &bus->i2c_client;
 347        int v = 0;
 348        u8 addr[2] = { 0, 0 };
 349        u8 buf[4] = { 0, 0, 0, 0 };
 350
 351        struct i2c_msg msgs[2] = {
 352                {
 353                        .addr = client->addr,
 354                        .flags = 0,
 355                        .len = 2,
 356                        .buf = addr,
 357                }, {
 358                        .addr = client->addr,
 359                        .flags = I2C_M_RD,
 360                        .len = 4,
 361                        .buf = buf,
 362                }
 363        };
 364
 365        addr[0] = (reg_addr >> 8);
 366        addr[1] = (reg_addr & 0xff);
 367        msgs[0].addr = 0x44;
 368        msgs[1].addr = 0x44;
 369
 370        i2c_xfer(client->adapter, msgs, 2);
 371
 372        v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
 373        *value = v;
 374
 375        return v;
 376}
 377
 378int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
 379{
 380        struct i2c_client *client = &bus->i2c_client;
 381        int retval = 0;
 382        u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
 383
 384        struct i2c_msg msgs[1] = {
 385                {
 386                        .addr = client->addr,
 387                        .flags = 0,
 388                        .len = 6,
 389                        .buf = buf,
 390                }
 391        };
 392
 393        buf[0] = reg_addr >> 8;
 394        buf[1] = reg_addr & 0xff;
 395        buf[5] = (value >> 24) & 0xff;
 396        buf[4] = (value >> 16) & 0xff;
 397        buf[3] = (value >> 8) & 0xff;
 398        buf[2] = value & 0xff;
 399        client->flags = 0;
 400        msgs[0].addr = 0x44;
 401
 402        retval = i2c_xfer(client->adapter, msgs, 1);
 403
 404        return retval;
 405}
 406