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