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