xref: /OK3568_Linux_fs/kernel/drivers/media/pci/mantis/mantis_i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun 	Mantis PCI bridge driver
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun 	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <asm/io.h>
10*4882a593Smuzhiyun #include <linux/ioport.h>
11*4882a593Smuzhiyun #include <linux/pci.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <media/dmxdev.h>
15*4882a593Smuzhiyun #include <media/dvbdev.h>
16*4882a593Smuzhiyun #include <media/dvb_demux.h>
17*4882a593Smuzhiyun #include <media/dvb_frontend.h>
18*4882a593Smuzhiyun #include <media/dvb_net.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "mantis_common.h"
21*4882a593Smuzhiyun #include "mantis_reg.h"
22*4882a593Smuzhiyun #include "mantis_i2c.h"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define TRIALS			10000
25*4882a593Smuzhiyun 
mantis_i2c_read(struct mantis_pci * mantis,const struct i2c_msg * msg)26*4882a593Smuzhiyun static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	u32 rxd, i, stat, trials;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
31*4882a593Smuzhiyun 		__func__, msg->addr);
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	for (i = 0; i < msg->len; i++) {
34*4882a593Smuzhiyun 		rxd = (msg->addr << 25) | (1 << 24)
35*4882a593Smuzhiyun 					| MANTIS_I2C_RATE_3
36*4882a593Smuzhiyun 					| MANTIS_I2C_STOP
37*4882a593Smuzhiyun 					| MANTIS_I2C_PGMODE;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 		if (i == (msg->len - 1))
40*4882a593Smuzhiyun 			rxd &= ~MANTIS_I2C_STOP;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
43*4882a593Smuzhiyun 		mmwrite(rxd, MANTIS_I2CDATA_CTL);
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 		/* wait for xfer completion */
46*4882a593Smuzhiyun 		for (trials = 0; trials < TRIALS; trials++) {
47*4882a593Smuzhiyun 			stat = mmread(MANTIS_INT_STAT);
48*4882a593Smuzhiyun 			if (stat & MANTIS_INT_I2CDONE)
49*4882a593Smuzhiyun 				break;
50*4882a593Smuzhiyun 		}
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 		/* wait for xfer completion */
55*4882a593Smuzhiyun 		for (trials = 0; trials < TRIALS; trials++) {
56*4882a593Smuzhiyun 			stat = mmread(MANTIS_INT_STAT);
57*4882a593Smuzhiyun 			if (stat & MANTIS_INT_I2CRACK)
58*4882a593Smuzhiyun 				break;
59*4882a593Smuzhiyun 		}
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 		rxd = mmread(MANTIS_I2CDATA_CTL);
64*4882a593Smuzhiyun 		msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
65*4882a593Smuzhiyun 		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 	dprintk(MANTIS_INFO, 0, "]\n");
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	return 0;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
mantis_i2c_write(struct mantis_pci * mantis,const struct i2c_msg * msg)72*4882a593Smuzhiyun static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	int i;
75*4882a593Smuzhiyun 	u32 txd = 0, stat, trials;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
78*4882a593Smuzhiyun 		__func__, msg->addr);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	for (i = 0; i < msg->len; i++) {
81*4882a593Smuzhiyun 		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
82*4882a593Smuzhiyun 		txd = (msg->addr << 25) | (msg->buf[i] << 8)
83*4882a593Smuzhiyun 					| MANTIS_I2C_RATE_3
84*4882a593Smuzhiyun 					| MANTIS_I2C_STOP
85*4882a593Smuzhiyun 					| MANTIS_I2C_PGMODE;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 		if (i == (msg->len - 1))
88*4882a593Smuzhiyun 			txd &= ~MANTIS_I2C_STOP;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
91*4882a593Smuzhiyun 		mmwrite(txd, MANTIS_I2CDATA_CTL);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		/* wait for xfer completion */
94*4882a593Smuzhiyun 		for (trials = 0; trials < TRIALS; trials++) {
95*4882a593Smuzhiyun 			stat = mmread(MANTIS_INT_STAT);
96*4882a593Smuzhiyun 			if (stat & MANTIS_INT_I2CDONE)
97*4882a593Smuzhiyun 				break;
98*4882a593Smuzhiyun 		}
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 		/* wait for xfer completion */
103*4882a593Smuzhiyun 		for (trials = 0; trials < TRIALS; trials++) {
104*4882a593Smuzhiyun 			stat = mmread(MANTIS_INT_STAT);
105*4882a593Smuzhiyun 			if (stat & MANTIS_INT_I2CRACK)
106*4882a593Smuzhiyun 				break;
107*4882a593Smuzhiyun 		}
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 	dprintk(MANTIS_INFO, 0, "]\n");
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
mantis_i2c_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)116*4882a593Smuzhiyun static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	int ret = 0, i = 0, trials;
119*4882a593Smuzhiyun 	u32 stat, data, txd;
120*4882a593Smuzhiyun 	struct mantis_pci *mantis;
121*4882a593Smuzhiyun 	struct mantis_hwconfig *config;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	mantis = i2c_get_adapdata(adapter);
124*4882a593Smuzhiyun 	BUG_ON(!mantis);
125*4882a593Smuzhiyun 	config = mantis->hwconfig;
126*4882a593Smuzhiyun 	BUG_ON(!config);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
129*4882a593Smuzhiyun 	mutex_lock(&mantis->i2c_lock);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	while (i < num) {
132*4882a593Smuzhiyun 		/* Byte MODE */
133*4882a593Smuzhiyun 		if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
134*4882a593Smuzhiyun 		    ((i + 1) < num)			&&
135*4882a593Smuzhiyun 		    (msgs[i].len < 2)			&&
136*4882a593Smuzhiyun 		    (msgs[i + 1].len < 2)		&&
137*4882a593Smuzhiyun 		    (msgs[i + 1].flags & I2C_M_RD)) {
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 			dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 			/* Read operation */
142*4882a593Smuzhiyun 			txd = msgs[i].addr << 25 | (0x1 << 24)
143*4882a593Smuzhiyun 						 | (msgs[i].buf[0] << 16)
144*4882a593Smuzhiyun 						 | MANTIS_I2C_RATE_3;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 			mmwrite(txd, MANTIS_I2CDATA_CTL);
147*4882a593Smuzhiyun 			/* wait for xfer completion */
148*4882a593Smuzhiyun 			for (trials = 0; trials < TRIALS; trials++) {
149*4882a593Smuzhiyun 				stat = mmread(MANTIS_INT_STAT);
150*4882a593Smuzhiyun 				if (stat & MANTIS_INT_I2CDONE)
151*4882a593Smuzhiyun 					break;
152*4882a593Smuzhiyun 			}
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 			/* check for xfer completion */
155*4882a593Smuzhiyun 			if (stat & MANTIS_INT_I2CDONE) {
156*4882a593Smuzhiyun 				/* check xfer was acknowledged */
157*4882a593Smuzhiyun 				if (stat & MANTIS_INT_I2CRACK) {
158*4882a593Smuzhiyun 					data = mmread(MANTIS_I2CDATA_CTL);
159*4882a593Smuzhiyun 					msgs[i + 1].buf[0] = (data >> 8) & 0xff;
160*4882a593Smuzhiyun 					dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
161*4882a593Smuzhiyun 				} else {
162*4882a593Smuzhiyun 					/* I/O error */
163*4882a593Smuzhiyun 					dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
164*4882a593Smuzhiyun 					ret = -EIO;
165*4882a593Smuzhiyun 					break;
166*4882a593Smuzhiyun 				}
167*4882a593Smuzhiyun 			} else {
168*4882a593Smuzhiyun 				/* I/O error */
169*4882a593Smuzhiyun 				dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
170*4882a593Smuzhiyun 				ret = -EIO;
171*4882a593Smuzhiyun 				break;
172*4882a593Smuzhiyun 			}
173*4882a593Smuzhiyun 			i += 2; /* Write/Read operation in one go */
174*4882a593Smuzhiyun 		}
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 		if (i < num) {
177*4882a593Smuzhiyun 			if (msgs[i].flags & I2C_M_RD)
178*4882a593Smuzhiyun 				ret = mantis_i2c_read(mantis, &msgs[i]);
179*4882a593Smuzhiyun 			else
180*4882a593Smuzhiyun 				ret = mantis_i2c_write(mantis, &msgs[i]);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 			i++;
183*4882a593Smuzhiyun 			if (ret < 0)
184*4882a593Smuzhiyun 				goto bail_out;
185*4882a593Smuzhiyun 		}
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	mutex_unlock(&mantis->i2c_lock);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	return num;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun bail_out:
194*4882a593Smuzhiyun 	mutex_unlock(&mantis->i2c_lock);
195*4882a593Smuzhiyun 	return ret;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
mantis_i2c_func(struct i2c_adapter * adapter)198*4882a593Smuzhiyun static u32 mantis_i2c_func(struct i2c_adapter *adapter)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	return I2C_FUNC_SMBUS_EMUL;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun static const struct i2c_algorithm mantis_algo = {
204*4882a593Smuzhiyun 	.master_xfer		= mantis_i2c_xfer,
205*4882a593Smuzhiyun 	.functionality		= mantis_i2c_func,
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun 
mantis_i2c_init(struct mantis_pci * mantis)208*4882a593Smuzhiyun int mantis_i2c_init(struct mantis_pci *mantis)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	u32 intstat;
211*4882a593Smuzhiyun 	struct i2c_adapter *i2c_adapter = &mantis->adapter;
212*4882a593Smuzhiyun 	struct pci_dev *pdev		= mantis->pdev;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	init_waitqueue_head(&mantis->i2c_wq);
215*4882a593Smuzhiyun 	mutex_init(&mantis->i2c_lock);
216*4882a593Smuzhiyun 	strscpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
217*4882a593Smuzhiyun 	i2c_set_adapdata(i2c_adapter, mantis);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	i2c_adapter->owner	= THIS_MODULE;
220*4882a593Smuzhiyun 	i2c_adapter->algo	= &mantis_algo;
221*4882a593Smuzhiyun 	i2c_adapter->algo_data	= NULL;
222*4882a593Smuzhiyun 	i2c_adapter->timeout	= 500;
223*4882a593Smuzhiyun 	i2c_adapter->retries	= 3;
224*4882a593Smuzhiyun 	i2c_adapter->dev.parent	= &pdev->dev;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	mantis->i2c_rc		= i2c_add_adapter(i2c_adapter);
227*4882a593Smuzhiyun 	if (mantis->i2c_rc < 0)
228*4882a593Smuzhiyun 		return mantis->i2c_rc;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	intstat = mmread(MANTIS_INT_STAT);
233*4882a593Smuzhiyun 	mmread(MANTIS_INT_MASK);
234*4882a593Smuzhiyun 	mmwrite(intstat, MANTIS_INT_STAT);
235*4882a593Smuzhiyun 	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
236*4882a593Smuzhiyun 	mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mantis_i2c_init);
241*4882a593Smuzhiyun 
mantis_i2c_exit(struct mantis_pci * mantis)242*4882a593Smuzhiyun int mantis_i2c_exit(struct mantis_pci *mantis)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
245*4882a593Smuzhiyun 	mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
248*4882a593Smuzhiyun 	i2c_del_adapter(&mantis->adapter);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mantis_i2c_exit);
253