509 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt3 4#include <linux/i2c.h>5#include <linux/mutex.h>6#include <linux/module.h>7 8#include "dibx000_common.h"9 10static int debug;11module_param(debug, int, 0644);12MODULE_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 20static 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(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;41 mutex_unlock(&mst->i2c_buffer_lock);42 43 return ret;44}45 46static 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(mst->i2c_adap, mst->msg, 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(&mst->i2c_buffer_lock);73 74 return ret;75}76 77static 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, 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 96static 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, 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, mst->base_reg, 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, mst->base_reg+1, da);130 131 if (dibx000_is_i2c_done(mst) != 0)132 return -EREMOTEIO;133 txlen -= len;134 }135 136 return 0;137}138 139static 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, mst->base_reg+1, 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, 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 182int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)183{184 struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);185 186 if (mst->device_rev < DIB7000MC && speed < 235)187 speed = 235;188 return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));189 190}191EXPORT_SYMBOL(dibx000_i2c_set_speed);192 193static u32 dibx000_i2c_func(struct i2c_adapter *adapter)194{195 return I2C_FUNC_I2C;196}197 198static 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, mst->base_reg + 4, intf);205 }206 return 0;207}208 209static 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(i2c_adap);212 int msg_index;213 int ret = 0;214 215 dibx000_i2c_select_interface(mst, 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_index]);219 if (ret != 0)220 return 0;221 } else {222 ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);223 if (ret != 0)224 return 0;225 }226 }227 228 return num;229}230 231static 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(i2c_adap);234 int msg_index;235 int ret = 0;236 237 dibx000_i2c_select_interface(mst, 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_index]);241 if (ret != 0)242 return 0;243 } else {244 ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);245 if (ret != 0)246 return 0;247 }248 }249 250 return num;251}252 253static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {254 .master_xfer = dibx000_i2c_master_xfer_gpio12,255 .functionality = dibx000_i2c_func,256};257 258static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {259 .master_xfer = dibx000_i2c_master_xfer_gpio34,260 .functionality = dibx000_i2c_func,261};262 263static 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 open271 else272 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 285static 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(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, 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, &mst->i2c_write_buffer[0], msg[0].addr, 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, &mst->i2c_write_buffer[4], 0, 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(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?321 num : -EIO);322 323 mutex_unlock(&mst->i2c_buffer_lock);324 return ret;325}326 327static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {328 .master_xfer = dibx000_i2c_gated_gpio67_xfer,329 .functionality = dibx000_i2c_func,330};331 332static 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(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, 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, &mst->i2c_write_buffer[0], msg[0].addr, 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, &mst->i2c_write_buffer[4], 0, 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(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?367 num : -EIO);368 mutex_unlock(&mst->i2c_buffer_lock);369 return ret;370}371 372static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {373 .master_xfer = dibx000_i2c_gated_tuner_xfer,374 .functionality = dibx000_i2c_func,375};376 377struct 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 408EXPORT_SYMBOL(dibx000_get_i2c_adapter);409 410void 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, 0, 0);417 i2c_transfer(mst->i2c_adap, &m, 1);418 mst->selected_interface = 0xff; // the first time force a select of the I2C419 dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);420}421 422EXPORT_SYMBOL(dibx000_reset_i2c_master);423 424static 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(i2c_adap, mst);432 if (i2c_add_adapter(i2c_adap) < 0)433 return -ENODEV;434 return 0;435}436 437int 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 else460 mst->base_reg = 768;461 462 mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;463 if (i2c_adapter_init464 (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,465 "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_init470 (&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,471 "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_init476 (&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,477 "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_init482 (&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,483 "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, mst->i2c_write_buffer, 0, 0);488 489 ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);490 mutex_unlock(&mst->i2c_buffer_lock);491 492 return ret;493}494 495EXPORT_SYMBOL(dibx000_init_i2c_master);496 497void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)498{499 i2c_del_adapter(&mst->gated_tuner_i2c_adap);500 i2c_del_adapter(&mst->master_i2c_adap_gpio12);501 i2c_del_adapter(&mst->master_i2c_adap_gpio34);502 i2c_del_adapter(&mst->master_i2c_adap_gpio67);503}504EXPORT_SYMBOL(dibx000_exit_i2c_master);505 506MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");507MODULE_DESCRIPTION("Common function the DiBcom demodulator family");508MODULE_LICENSE("GPL");509