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