]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/pci/mantis/mantis_i2c.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 61
[mirror_ubuntu-jammy-kernel.git] / drivers / media / pci / mantis / mantis_i2c.c
CommitLineData
74ba9207 1// SPDX-License-Identifier: GPL-2.0-or-later
41e840b1
MA
2/*
3 Mantis PCI bridge driver
4
8825a097 5 Copyright (C) Manu Abraham (abraham.manu@gmail.com)
41e840b1 6
41e840b1
MA
7*/
8
41e840b1
MA
9#include <asm/io.h>
10#include <linux/ioport.h>
b3b96144
MA
11#include <linux/pci.h>
12#include <linux/i2c.h>
13
fada1935
MCC
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>
b3b96144 19
41e840b1 20#include "mantis_common.h"
b3b96144
MA
21#include "mantis_reg.h"
22#include "mantis_i2c.h"
41e840b1 23
bc832fa2
MA
24#define TRIALS 10000
25
41e840b1
MA
26static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
27{
3e978a82 28 u32 rxd, i, stat, trials;
41e840b1 29
b3b96144 30 dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <R>[ ",
715d341c
MA
31 __func__, msg->addr);
32
41e840b1
MA
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
df0cca17 42 mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
41e840b1 43 mmwrite(rxd, MANTIS_I2CDATA_CTL);
3e978a82
MA
44
45 /* wait for xfer completion */
bc832fa2 46 for (trials = 0; trials < TRIALS; trials++) {
3e978a82
MA
47 stat = mmread(MANTIS_INT_STAT);
48 if (stat & MANTIS_INT_I2CDONE)
49 break;
41e840b1 50 }
3e978a82 51
bc832fa2
MA
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;
bc832fa2
MA
59 }
60
61 dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
62
41e840b1
MA
63 rxd = mmread(MANTIS_I2CDATA_CTL);
64 msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
b3b96144 65 dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
41e840b1 66 }
b3b96144 67 dprintk(MANTIS_INFO, 0, "]\n");
41e840b1
MA
68
69 return 0;
70}
71
72static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
73{
74 int i;
3e978a82 75 u32 txd = 0, stat, trials;
41e840b1 76
b3b96144 77 dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <W>[ ",
715d341c
MA
78 __func__, msg->addr);
79
41e840b1 80 for (i = 0; i < msg->len; i++) {
b3b96144 81 dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
41e840b1
MA
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
df0cca17 90 mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
41e840b1 91 mmwrite(txd, MANTIS_I2CDATA_CTL);
3e978a82
MA
92
93 /* wait for xfer completion */
bc832fa2 94 for (trials = 0; trials < TRIALS; trials++) {
3e978a82
MA
95 stat = mmread(MANTIS_INT_STAT);
96 if (stat & MANTIS_INT_I2CDONE)
97 break;
41e840b1 98 }
bc832fa2
MA
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;
bc832fa2
MA
107 }
108
109 dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
41e840b1 110 }
b3b96144 111 dprintk(MANTIS_INFO, 0, "]\n");
41e840b1
MA
112
113 return 0;
114}
115
116static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
117{
3e978a82
MA
118 int ret = 0, i = 0, trials;
119 u32 stat, data, txd;
41e840b1 120 struct mantis_pci *mantis;
3e978a82 121 struct mantis_hwconfig *config;
41e840b1
MA
122
123 mantis = i2c_get_adapdata(adapter);
3e978a82
MA
124 BUG_ON(!mantis);
125 config = mantis->hwconfig;
126 BUG_ON(!config);
127
128 dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
e2f67e4f 129 mutex_lock(&mantis->i2c_lock);
3e978a82
MA
130
131 while (i < num) {
132 /* Byte MODE */
bc832fa2
MA
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)) {
3e978a82
MA
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 */
bc832fa2 148 for (trials = 0; trials < TRIALS; trials++) {
3e978a82
MA
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
41e840b1 187 }
3e978a82 188
e2f67e4f 189 mutex_unlock(&mantis->i2c_lock);
41e840b1
MA
190
191 return num;
99d96e4e
MA
192
193bail_out:
194 mutex_unlock(&mantis->i2c_lock);
195 return ret;
41e840b1
MA
196}
197
198static u32 mantis_i2c_func(struct i2c_adapter *adapter)
199{
200 return I2C_FUNC_SMBUS_EMUL;
201}
202
e46ab9dc 203static const struct i2c_algorithm mantis_algo = {
41e840b1
MA
204 .master_xfer = mantis_i2c_xfer,
205 .functionality = mantis_i2c_func,
206};
207
4c62e976 208int mantis_i2c_init(struct mantis_pci *mantis)
41e840b1 209{
6fe2d69c 210 u32 intstat;
8154bad4
MA
211 struct i2c_adapter *i2c_adapter = &mantis->adapter;
212 struct pci_dev *pdev = mantis->pdev;
41e840b1 213
b3b96144 214 init_waitqueue_head(&mantis->i2c_wq);
e2f67e4f 215 mutex_init(&mantis->i2c_lock);
85709cbf 216 strscpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
8154bad4
MA
217 i2c_set_adapdata(i2c_adapter, mantis);
218
b3b96144 219 i2c_adapter->owner = THIS_MODULE;
b3b96144
MA
220 i2c_adapter->algo = &mantis_algo;
221 i2c_adapter->algo_data = NULL;
b3b96144
MA
222 i2c_adapter->timeout = 500;
223 i2c_adapter->retries = 3;
224 i2c_adapter->dev.parent = &pdev->dev;
225
8154bad4 226 mantis->i2c_rc = i2c_add_adapter(i2c_adapter);
41e840b1
MA
227 if (mantis->i2c_rc < 0)
228 return mantis->i2c_rc;
229
b3b96144 230 dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
41e840b1 231
41e840b1 232 intstat = mmread(MANTIS_INT_STAT);
6fe2d69c 233 mmread(MANTIS_INT_MASK);
41e840b1 234 mmwrite(intstat, MANTIS_INT_STAT);
3e978a82 235 dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
a96762da 236 mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
41e840b1
MA
237
238 return 0;
239}
b3b96144 240EXPORT_SYMBOL_GPL(mantis_i2c_init);
41e840b1 241
4cf0b3f1 242int mantis_i2c_exit(struct mantis_pci *mantis)
41e840b1 243{
3e978a82 244 dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
a96762da 245 mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
3e978a82 246
b3b96144 247 dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
bf51a8c5
LPC
248 i2c_del_adapter(&mantis->adapter);
249
250 return 0;
41e840b1 251}
b3b96144 252EXPORT_SYMBOL_GPL(mantis_i2c_exit);