Merge tag 'regulator-fix-v5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / media / pci / mantis / mantis_i2c.c
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);