1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
3 | |
4 | #include <linux/i2c.h> |
5 | #include <linux/mutex.h> |
6 | #include <linux/module.h> |
7 | |
8 | #include "dibx000_common.h" |
9 | |
10 | static int debug; |
11 | module_param(debug, int, 0644); |
12 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)" ); |
13 | |
14 | #define dprintk(fmt, arg...) do { \ |
15 | if (debug) \ |
16 | printk(KERN_DEBUG pr_fmt("%s: " fmt), \ |
17 | __func__, ##arg); \ |
18 | } while (0) |
19 | |
20 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) |
21 | { |
22 | int ret; |
23 | |
24 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { |
25 | dprintk("could not acquire lock\n" ); |
26 | return -EINVAL; |
27 | } |
28 | |
29 | mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; |
30 | mst->i2c_write_buffer[1] = reg & 0xff; |
31 | mst->i2c_write_buffer[2] = (val >> 8) & 0xff; |
32 | mst->i2c_write_buffer[3] = val & 0xff; |
33 | |
34 | memset(mst->msg, 0, sizeof(struct i2c_msg)); |
35 | mst->msg[0].addr = mst->i2c_addr; |
36 | mst->msg[0].flags = 0; |
37 | mst->msg[0].buf = mst->i2c_write_buffer; |
38 | mst->msg[0].len = 4; |
39 | |
40 | ret = i2c_transfer(adap: mst->i2c_adap, msgs: mst->msg, num: 1) != 1 ? -EREMOTEIO : 0; |
41 | mutex_unlock(lock: &mst->i2c_buffer_lock); |
42 | |
43 | return ret; |
44 | } |
45 | |
46 | static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) |
47 | { |
48 | u16 ret; |
49 | |
50 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { |
51 | dprintk("could not acquire lock\n" ); |
52 | return 0; |
53 | } |
54 | |
55 | mst->i2c_write_buffer[0] = reg >> 8; |
56 | mst->i2c_write_buffer[1] = reg & 0xff; |
57 | |
58 | memset(mst->msg, 0, 2 * sizeof(struct i2c_msg)); |
59 | mst->msg[0].addr = mst->i2c_addr; |
60 | mst->msg[0].flags = 0; |
61 | mst->msg[0].buf = mst->i2c_write_buffer; |
62 | mst->msg[0].len = 2; |
63 | mst->msg[1].addr = mst->i2c_addr; |
64 | mst->msg[1].flags = I2C_M_RD; |
65 | mst->msg[1].buf = mst->i2c_read_buffer; |
66 | mst->msg[1].len = 2; |
67 | |
68 | if (i2c_transfer(adap: mst->i2c_adap, msgs: mst->msg, num: 2) != 2) |
69 | dprintk("i2c read error on %d\n" , reg); |
70 | |
71 | ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; |
72 | mutex_unlock(lock: &mst->i2c_buffer_lock); |
73 | |
74 | return ret; |
75 | } |
76 | |
77 | static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) |
78 | { |
79 | int i = 100; |
80 | u16 status; |
81 | |
82 | while (((status = dibx000_read_word(mst, reg: mst->base_reg + 2)) & 0x0100) == 0 && --i > 0) |
83 | ; |
84 | |
85 | /* i2c timed out */ |
86 | if (i == 0) |
87 | return -EREMOTEIO; |
88 | |
89 | /* no acknowledge */ |
90 | if ((status & 0x0080) == 0) |
91 | return -EREMOTEIO; |
92 | |
93 | return 0; |
94 | } |
95 | |
96 | static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop) |
97 | { |
98 | u16 data; |
99 | u16 da; |
100 | u16 i; |
101 | u16 txlen = msg->len, len; |
102 | const u8 *b = msg->buf; |
103 | |
104 | while (txlen) { |
105 | dibx000_read_word(mst, reg: mst->base_reg + 2); |
106 | |
107 | len = txlen > 8 ? 8 : txlen; |
108 | for (i = 0; i < len; i += 2) { |
109 | data = *b++ << 8; |
110 | if (i+1 < len) |
111 | data |= *b++; |
112 | dibx000_write_word(mst, reg: mst->base_reg, val: data); |
113 | } |
114 | da = (((u8) (msg->addr)) << 9) | |
115 | (1 << 8) | |
116 | (1 << 7) | |
117 | (0 << 6) | |
118 | (0 << 5) | |
119 | ((len & 0x7) << 2) | |
120 | (0 << 1) | |
121 | (0 << 0); |
122 | |
123 | if (txlen == msg->len) |
124 | da |= 1 << 5; /* start */ |
125 | |
126 | if (txlen-len == 0 && stop) |
127 | da |= 1 << 6; /* stop */ |
128 | |
129 | dibx000_write_word(mst, reg: mst->base_reg+1, val: da); |
130 | |
131 | if (dibx000_is_i2c_done(mst) != 0) |
132 | return -EREMOTEIO; |
133 | txlen -= len; |
134 | } |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg) |
140 | { |
141 | u16 da; |
142 | u8 *b = msg->buf; |
143 | u16 rxlen = msg->len, len; |
144 | |
145 | while (rxlen) { |
146 | len = rxlen > 8 ? 8 : rxlen; |
147 | da = (((u8) (msg->addr)) << 9) | |
148 | (1 << 8) | |
149 | (1 << 7) | |
150 | (0 << 6) | |
151 | (0 << 5) | |
152 | ((len & 0x7) << 2) | |
153 | (1 << 1) | |
154 | (0 << 0); |
155 | |
156 | if (rxlen == msg->len) |
157 | da |= 1 << 5; /* start */ |
158 | |
159 | if (rxlen-len == 0) |
160 | da |= 1 << 6; /* stop */ |
161 | dibx000_write_word(mst, reg: mst->base_reg+1, val: da); |
162 | |
163 | if (dibx000_is_i2c_done(mst) != 0) |
164 | return -EREMOTEIO; |
165 | |
166 | rxlen -= len; |
167 | |
168 | while (len) { |
169 | da = dibx000_read_word(mst, reg: mst->base_reg); |
170 | *b++ = (da >> 8) & 0xff; |
171 | len--; |
172 | if (len >= 1) { |
173 | *b++ = da & 0xff; |
174 | len--; |
175 | } |
176 | } |
177 | } |
178 | |
179 | return 0; |
180 | } |
181 | |
182 | int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed) |
183 | { |
184 | struct dibx000_i2c_master *mst = i2c_get_adapdata(adap: i2c_adap); |
185 | |
186 | if (mst->device_rev < DIB7000MC && speed < 235) |
187 | speed = 235; |
188 | return dibx000_write_word(mst, reg: mst->base_reg + 3, val: (u16)(60000 / speed)); |
189 | |
190 | } |
191 | EXPORT_SYMBOL(dibx000_i2c_set_speed); |
192 | |
193 | static u32 dibx000_i2c_func(struct i2c_adapter *adapter) |
194 | { |
195 | return I2C_FUNC_I2C; |
196 | } |
197 | |
198 | static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, |
199 | enum dibx000_i2c_interface intf) |
200 | { |
201 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { |
202 | dprintk("selecting interface: %d\n" , intf); |
203 | mst->selected_interface = intf; |
204 | return dibx000_write_word(mst, reg: mst->base_reg + 4, val: intf); |
205 | } |
206 | return 0; |
207 | } |
208 | |
209 | static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) |
210 | { |
211 | struct dibx000_i2c_master *mst = i2c_get_adapdata(adap: i2c_adap); |
212 | int msg_index; |
213 | int ret = 0; |
214 | |
215 | dibx000_i2c_select_interface(mst, intf: DIBX000_I2C_INTERFACE_GPIO_1_2); |
216 | for (msg_index = 0; msg_index < num; msg_index++) { |
217 | if (msg[msg_index].flags & I2C_M_RD) { |
218 | ret = dibx000_master_i2c_read(mst, msg: &msg[msg_index]); |
219 | if (ret != 0) |
220 | return 0; |
221 | } else { |
222 | ret = dibx000_master_i2c_write(mst, msg: &msg[msg_index], stop: 1); |
223 | if (ret != 0) |
224 | return 0; |
225 | } |
226 | } |
227 | |
228 | return num; |
229 | } |
230 | |
231 | static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) |
232 | { |
233 | struct dibx000_i2c_master *mst = i2c_get_adapdata(adap: i2c_adap); |
234 | int msg_index; |
235 | int ret = 0; |
236 | |
237 | dibx000_i2c_select_interface(mst, intf: DIBX000_I2C_INTERFACE_GPIO_3_4); |
238 | for (msg_index = 0; msg_index < num; msg_index++) { |
239 | if (msg[msg_index].flags & I2C_M_RD) { |
240 | ret = dibx000_master_i2c_read(mst, msg: &msg[msg_index]); |
241 | if (ret != 0) |
242 | return 0; |
243 | } else { |
244 | ret = dibx000_master_i2c_write(mst, msg: &msg[msg_index], stop: 1); |
245 | if (ret != 0) |
246 | return 0; |
247 | } |
248 | } |
249 | |
250 | return num; |
251 | } |
252 | |
253 | static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = { |
254 | .master_xfer = dibx000_i2c_master_xfer_gpio12, |
255 | .functionality = dibx000_i2c_func, |
256 | }; |
257 | |
258 | static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = { |
259 | .master_xfer = dibx000_i2c_master_xfer_gpio34, |
260 | .functionality = dibx000_i2c_func, |
261 | }; |
262 | |
263 | static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], |
264 | u8 addr, int onoff) |
265 | { |
266 | u16 val; |
267 | |
268 | |
269 | if (onoff) |
270 | val = addr << 8; // bit 7 = use master or not, if 0, the gate is open |
271 | else |
272 | val = 1 << 7; |
273 | |
274 | if (mst->device_rev > DIB7000) |
275 | val <<= 1; |
276 | |
277 | tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); |
278 | tx[1] = ((mst->base_reg + 1) & 0xff); |
279 | tx[2] = val >> 8; |
280 | tx[3] = val & 0xff; |
281 | |
282 | return 0; |
283 | } |
284 | |
285 | static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, |
286 | struct i2c_msg msg[], int num) |
287 | { |
288 | struct dibx000_i2c_master *mst = i2c_get_adapdata(adap: i2c_adap); |
289 | int ret; |
290 | |
291 | if (num > 32) { |
292 | dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32" , |
293 | __func__, num); |
294 | return -ENOMEM; |
295 | } |
296 | |
297 | dibx000_i2c_select_interface(mst, intf: DIBX000_I2C_INTERFACE_GPIO_6_7); |
298 | |
299 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { |
300 | dprintk("could not acquire lock\n" ); |
301 | return -EINVAL; |
302 | } |
303 | |
304 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); |
305 | |
306 | /* open the gate */ |
307 | dibx000_i2c_gate_ctrl(mst, tx: &mst->i2c_write_buffer[0], addr: msg[0].addr, onoff: 1); |
308 | mst->msg[0].addr = mst->i2c_addr; |
309 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; |
310 | mst->msg[0].len = 4; |
311 | |
312 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); |
313 | |
314 | /* close the gate */ |
315 | dibx000_i2c_gate_ctrl(mst, tx: &mst->i2c_write_buffer[4], addr: 0, onoff: 0); |
316 | mst->msg[num + 1].addr = mst->i2c_addr; |
317 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; |
318 | mst->msg[num + 1].len = 4; |
319 | |
320 | ret = (i2c_transfer(adap: mst->i2c_adap, msgs: mst->msg, num: 2 + num) == 2 + num ? |
321 | num : -EIO); |
322 | |
323 | mutex_unlock(lock: &mst->i2c_buffer_lock); |
324 | return ret; |
325 | } |
326 | |
327 | static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { |
328 | .master_xfer = dibx000_i2c_gated_gpio67_xfer, |
329 | .functionality = dibx000_i2c_func, |
330 | }; |
331 | |
332 | static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, |
333 | struct i2c_msg msg[], int num) |
334 | { |
335 | struct dibx000_i2c_master *mst = i2c_get_adapdata(adap: i2c_adap); |
336 | int ret; |
337 | |
338 | if (num > 32) { |
339 | dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32" , |
340 | __func__, num); |
341 | return -ENOMEM; |
342 | } |
343 | |
344 | dibx000_i2c_select_interface(mst, intf: DIBX000_I2C_INTERFACE_TUNER); |
345 | |
346 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { |
347 | dprintk("could not acquire lock\n" ); |
348 | return -EINVAL; |
349 | } |
350 | memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); |
351 | |
352 | /* open the gate */ |
353 | dibx000_i2c_gate_ctrl(mst, tx: &mst->i2c_write_buffer[0], addr: msg[0].addr, onoff: 1); |
354 | mst->msg[0].addr = mst->i2c_addr; |
355 | mst->msg[0].buf = &mst->i2c_write_buffer[0]; |
356 | mst->msg[0].len = 4; |
357 | |
358 | memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); |
359 | |
360 | /* close the gate */ |
361 | dibx000_i2c_gate_ctrl(mst, tx: &mst->i2c_write_buffer[4], addr: 0, onoff: 0); |
362 | mst->msg[num + 1].addr = mst->i2c_addr; |
363 | mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; |
364 | mst->msg[num + 1].len = 4; |
365 | |
366 | ret = (i2c_transfer(adap: mst->i2c_adap, msgs: mst->msg, num: 2 + num) == 2 + num ? |
367 | num : -EIO); |
368 | mutex_unlock(lock: &mst->i2c_buffer_lock); |
369 | return ret; |
370 | } |
371 | |
372 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { |
373 | .master_xfer = dibx000_i2c_gated_tuner_xfer, |
374 | .functionality = dibx000_i2c_func, |
375 | }; |
376 | |
377 | struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, |
378 | enum dibx000_i2c_interface intf, |
379 | int gating) |
380 | { |
381 | struct i2c_adapter *i2c = NULL; |
382 | |
383 | switch (intf) { |
384 | case DIBX000_I2C_INTERFACE_TUNER: |
385 | if (gating) |
386 | i2c = &mst->gated_tuner_i2c_adap; |
387 | break; |
388 | case DIBX000_I2C_INTERFACE_GPIO_1_2: |
389 | if (!gating) |
390 | i2c = &mst->master_i2c_adap_gpio12; |
391 | break; |
392 | case DIBX000_I2C_INTERFACE_GPIO_3_4: |
393 | if (!gating) |
394 | i2c = &mst->master_i2c_adap_gpio34; |
395 | break; |
396 | case DIBX000_I2C_INTERFACE_GPIO_6_7: |
397 | if (gating) |
398 | i2c = &mst->master_i2c_adap_gpio67; |
399 | break; |
400 | default: |
401 | pr_err("incorrect I2C interface selected\n" ); |
402 | break; |
403 | } |
404 | |
405 | return i2c; |
406 | } |
407 | |
408 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); |
409 | |
410 | void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst) |
411 | { |
412 | /* initialize the i2c-master by closing the gate */ |
413 | u8 tx[4]; |
414 | struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 }; |
415 | |
416 | dibx000_i2c_gate_ctrl(mst, tx, addr: 0, onoff: 0); |
417 | i2c_transfer(adap: mst->i2c_adap, msgs: &m, num: 1); |
418 | mst->selected_interface = 0xff; // the first time force a select of the I2C |
419 | dibx000_i2c_select_interface(mst, intf: DIBX000_I2C_INTERFACE_TUNER); |
420 | } |
421 | |
422 | EXPORT_SYMBOL(dibx000_reset_i2c_master); |
423 | |
424 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, |
425 | struct i2c_algorithm *algo, const char *name, |
426 | struct dibx000_i2c_master *mst) |
427 | { |
428 | strscpy(i2c_adap->name, name, sizeof(i2c_adap->name)); |
429 | i2c_adap->algo = algo; |
430 | i2c_adap->algo_data = NULL; |
431 | i2c_set_adapdata(adap: i2c_adap, data: mst); |
432 | if (i2c_add_adapter(adap: i2c_adap) < 0) |
433 | return -ENODEV; |
434 | return 0; |
435 | } |
436 | |
437 | int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, |
438 | struct i2c_adapter *i2c_adap, u8 i2c_addr) |
439 | { |
440 | int ret; |
441 | |
442 | mutex_init(&mst->i2c_buffer_lock); |
443 | if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { |
444 | dprintk("could not acquire lock\n" ); |
445 | return -EINVAL; |
446 | } |
447 | memset(mst->msg, 0, sizeof(struct i2c_msg)); |
448 | mst->msg[0].addr = i2c_addr >> 1; |
449 | mst->msg[0].flags = 0; |
450 | mst->msg[0].buf = mst->i2c_write_buffer; |
451 | mst->msg[0].len = 4; |
452 | |
453 | mst->device_rev = device_rev; |
454 | mst->i2c_adap = i2c_adap; |
455 | mst->i2c_addr = i2c_addr >> 1; |
456 | |
457 | if (device_rev == DIB7000P || device_rev == DIB8000) |
458 | mst->base_reg = 1024; |
459 | else |
460 | mst->base_reg = 768; |
461 | |
462 | mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent; |
463 | if (i2c_adapter_init |
464 | (i2c_adap: &mst->gated_tuner_i2c_adap, algo: &dibx000_i2c_gated_tuner_algo, |
465 | name: "DiBX000 tuner I2C bus" , mst) != 0) |
466 | pr_err("could not initialize the tuner i2c_adapter\n" ); |
467 | |
468 | mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent; |
469 | if (i2c_adapter_init |
470 | (i2c_adap: &mst->master_i2c_adap_gpio12, algo: &dibx000_i2c_master_gpio12_xfer_algo, |
471 | name: "DiBX000 master GPIO12 I2C bus" , mst) != 0) |
472 | pr_err("could not initialize the master i2c_adapter\n" ); |
473 | |
474 | mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent; |
475 | if (i2c_adapter_init |
476 | (i2c_adap: &mst->master_i2c_adap_gpio34, algo: &dibx000_i2c_master_gpio34_xfer_algo, |
477 | name: "DiBX000 master GPIO34 I2C bus" , mst) != 0) |
478 | pr_err("could not initialize the master i2c_adapter\n" ); |
479 | |
480 | mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent; |
481 | if (i2c_adapter_init |
482 | (i2c_adap: &mst->master_i2c_adap_gpio67, algo: &dibx000_i2c_gated_gpio67_algo, |
483 | name: "DiBX000 master GPIO67 I2C bus" , mst) != 0) |
484 | pr_err("could not initialize the master i2c_adapter\n" ); |
485 | |
486 | /* initialize the i2c-master by closing the gate */ |
487 | dibx000_i2c_gate_ctrl(mst, tx: mst->i2c_write_buffer, addr: 0, onoff: 0); |
488 | |
489 | ret = (i2c_transfer(adap: i2c_adap, msgs: mst->msg, num: 1) == 1); |
490 | mutex_unlock(lock: &mst->i2c_buffer_lock); |
491 | |
492 | return ret; |
493 | } |
494 | |
495 | EXPORT_SYMBOL(dibx000_init_i2c_master); |
496 | |
497 | void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) |
498 | { |
499 | i2c_del_adapter(adap: &mst->gated_tuner_i2c_adap); |
500 | i2c_del_adapter(adap: &mst->master_i2c_adap_gpio12); |
501 | i2c_del_adapter(adap: &mst->master_i2c_adap_gpio34); |
502 | i2c_del_adapter(adap: &mst->master_i2c_adap_gpio67); |
503 | } |
504 | EXPORT_SYMBOL(dibx000_exit_i2c_master); |
505 | |
506 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>" ); |
507 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family" ); |
508 | MODULE_LICENSE("GPL" ); |
509 | |