Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Driver for the NXP SAA7164 PCIe bridge
0004  *
0005  *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/moduleparam.h>
0010 #include <linux/init.h>
0011 #include <linux/delay.h>
0012 #include <linux/io.h>
0013 
0014 #include "saa7164.h"
0015 
0016 static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
0017 {
0018     struct saa7164_i2c *bus = i2c_adap->algo_data;
0019     struct saa7164_dev *dev = bus->dev;
0020     int i, retval = 0;
0021 
0022     dprintk(DBGLVL_I2C, "%s(num = %d)\n", __func__, num);
0023 
0024     for (i = 0 ; i < num; i++) {
0025         dprintk(DBGLVL_I2C, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
0026             __func__, num, msgs[i].addr, msgs[i].len);
0027         if (msgs[i].flags & I2C_M_RD) {
0028             retval = saa7164_api_i2c_read(bus,
0029                 msgs[i].addr,
0030                 0 /* reglen */,
0031                 NULL /* reg */, msgs[i].len, msgs[i].buf);
0032         } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
0033                msgs[i].addr == msgs[i + 1].addr) {
0034             /* write then read from same address */
0035 
0036             retval = saa7164_api_i2c_read(bus, msgs[i].addr,
0037                 msgs[i].len, msgs[i].buf,
0038                 msgs[i+1].len, msgs[i+1].buf
0039                 );
0040 
0041             i++;
0042 
0043             if (retval < 0)
0044                 goto err;
0045         } else {
0046             /* write */
0047             retval = saa7164_api_i2c_write(bus, msgs[i].addr,
0048                 msgs[i].len, msgs[i].buf);
0049         }
0050         if (retval < 0)
0051             goto err;
0052     }
0053     return num;
0054 
0055 err:
0056     return retval;
0057 }
0058 
0059 static u32 saa7164_functionality(struct i2c_adapter *adap)
0060 {
0061     return I2C_FUNC_I2C;
0062 }
0063 
0064 static const struct i2c_algorithm saa7164_i2c_algo_template = {
0065     .master_xfer    = i2c_xfer,
0066     .functionality  = saa7164_functionality,
0067 };
0068 
0069 /* ----------------------------------------------------------------------- */
0070 
0071 static const struct i2c_adapter saa7164_i2c_adap_template = {
0072     .name              = "saa7164",
0073     .owner             = THIS_MODULE,
0074     .algo              = &saa7164_i2c_algo_template,
0075 };
0076 
0077 static const struct i2c_client saa7164_i2c_client_template = {
0078     .name   = "saa7164 internal",
0079 };
0080 
0081 int saa7164_i2c_register(struct saa7164_i2c *bus)
0082 {
0083     struct saa7164_dev *dev = bus->dev;
0084 
0085     dprintk(DBGLVL_I2C, "%s(bus = %d)\n", __func__, bus->nr);
0086 
0087     bus->i2c_adap = saa7164_i2c_adap_template;
0088     bus->i2c_client = saa7164_i2c_client_template;
0089 
0090     bus->i2c_adap.dev.parent = &dev->pci->dev;
0091 
0092     strscpy(bus->i2c_adap.name, bus->dev->name,
0093         sizeof(bus->i2c_adap.name));
0094 
0095     bus->i2c_adap.algo_data = bus;
0096     i2c_set_adapdata(&bus->i2c_adap, bus);
0097     i2c_add_adapter(&bus->i2c_adap);
0098 
0099     bus->i2c_client.adapter = &bus->i2c_adap;
0100 
0101     if (0 != bus->i2c_rc)
0102         printk(KERN_ERR "%s: i2c bus %d register FAILED\n",
0103             dev->name, bus->nr);
0104 
0105     return bus->i2c_rc;
0106 }
0107 
0108 int saa7164_i2c_unregister(struct saa7164_i2c *bus)
0109 {
0110     i2c_del_adapter(&bus->i2c_adap);
0111     return 0;
0112 }