linux/drivers/media/pci/saa7164/saa7164-i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Driver for the NXP SAA7164 PCIe bridge
   4 *
   5 *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/moduleparam.h>
  10#include <linux/init.h>
  11#include <linux/delay.h>
  12#include <linux/io.h>
  13
  14#include "saa7164.h"
  15
  16static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
  17{
  18        struct saa7164_i2c *bus = i2c_adap->algo_data;
  19        struct saa7164_dev *dev = bus->dev;
  20        int i, retval = 0;
  21
  22        dprintk(DBGLVL_I2C, "%s(num = %d)\n", __func__, num);
  23
  24        for (i = 0 ; i < num; i++) {
  25                dprintk(DBGLVL_I2C, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
  26                        __func__, num, msgs[i].addr, msgs[i].len);
  27                if (msgs[i].flags & I2C_M_RD) {
  28                        retval = saa7164_api_i2c_read(bus,
  29                                msgs[i].addr,
  30                                0 /* reglen */,
  31                                NULL /* reg */, msgs[i].len, msgs[i].buf);
  32                } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
  33                           msgs[i].addr == msgs[i + 1].addr) {
  34                        /* write then read from same address */
  35
  36                        retval = saa7164_api_i2c_read(bus, msgs[i].addr,
  37                                msgs[i].len, msgs[i].buf,
  38                                msgs[i+1].len, msgs[i+1].buf
  39                                );
  40
  41                        i++;
  42
  43                        if (retval < 0)
  44                                goto err;
  45                } else {
  46                        /* write */
  47                        retval = saa7164_api_i2c_write(bus, msgs[i].addr,
  48                                msgs[i].len, msgs[i].buf);
  49                }
  50                if (retval < 0)
  51                        goto err;
  52        }
  53        return num;
  54
  55err:
  56        return retval;
  57}
  58
  59static u32 saa7164_functionality(struct i2c_adapter *adap)
  60{
  61        return I2C_FUNC_I2C;
  62}
  63
  64static const struct i2c_algorithm saa7164_i2c_algo_template = {
  65        .master_xfer    = i2c_xfer,
  66        .functionality  = saa7164_functionality,
  67};
  68
  69/* ----------------------------------------------------------------------- */
  70
  71static const struct i2c_adapter saa7164_i2c_adap_template = {
  72        .name              = "saa7164",
  73        .owner             = THIS_MODULE,
  74        .algo              = &saa7164_i2c_algo_template,
  75};
  76
  77static const struct i2c_client saa7164_i2c_client_template = {
  78        .name   = "saa7164 internal",
  79};
  80
  81int saa7164_i2c_register(struct saa7164_i2c *bus)
  82{
  83        struct saa7164_dev *dev = bus->dev;
  84
  85        dprintk(DBGLVL_I2C, "%s(bus = %d)\n", __func__, bus->nr);
  86
  87        bus->i2c_adap = saa7164_i2c_adap_template;
  88        bus->i2c_client = saa7164_i2c_client_template;
  89
  90        bus->i2c_adap.dev.parent = &dev->pci->dev;
  91
  92        strscpy(bus->i2c_adap.name, bus->dev->name,
  93                sizeof(bus->i2c_adap.name));
  94
  95        bus->i2c_adap.algo_data = bus;
  96        i2c_set_adapdata(&bus->i2c_adap, bus);
  97        i2c_add_adapter(&bus->i2c_adap);
  98
  99        bus->i2c_client.adapter = &bus->i2c_adap;
 100
 101        if (0 != bus->i2c_rc)
 102                printk(KERN_ERR "%s: i2c bus %d register FAILED\n",
 103                        dev->name, bus->nr);
 104
 105        return bus->i2c_rc;
 106}
 107
 108int saa7164_i2c_unregister(struct saa7164_i2c *bus)
 109{
 110        i2c_del_adapter(&bus->i2c_adap);
 111        return 0;
 112}
 113