Path: blob/master/drivers/media/dvb/b2c2/flexcop-i2c.c
15111 views
/*1* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III2* flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization3* see flexcop.c for copyright information4*/5#include "flexcop.h"67#define FC_MAX_I2C_RETRIES 10000089static int flexcop_i2c_operation(struct flexcop_device *fc,10flexcop_ibi_value *r100)11{12int i;13flexcop_ibi_value r;1415r100->tw_sm_c_100.working_start = 1;16deb_i2c("r100 before: %08x\n",r100->raw);1718fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);19fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */2021for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {22r = fc->read_ibi_reg(fc, tw_sm_c_100);2324if (!r.tw_sm_c_100.no_base_addr_ack_error) {25if (r.tw_sm_c_100.st_done) {26*r100 = r;27deb_i2c("i2c success\n");28return 0;29}30} else {31deb_i2c("suffering from an i2c ack_error\n");32return -EREMOTEIO;33}34}35deb_i2c("tried %d times i2c operation, "36"never finished or too many ack errors.\n", i);37return -EREMOTEIO;38}3940static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,41flexcop_ibi_value r100, u8 *buf)42{43flexcop_ibi_value r104;44int len = r100.tw_sm_c_100.total_bytes,45/* remember total_bytes is buflen-1 */46ret;4748/* work-around to have CableStar2 and SkyStar2 rev 2.7 work49* correctly:50*51* the ITD1000 is behind an i2c-gate which closes automatically52* after an i2c-transaction the STV0297 needs 2 consecutive reads53* one with no_base_addr = 0 and one with 154*55* those two work-arounds are conflictin: we check for the card56* type, it is set when probing the ITD1000 */57if (i2c->fc->dev_type == FC_SKY_REV27)58r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;5960ret = flexcop_i2c_operation(i2c->fc, &r100);61if (ret != 0) {62deb_i2c("Retrying operation\n");63r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;64ret = flexcop_i2c_operation(i2c->fc, &r100);65}66if (ret != 0) {67deb_i2c("read failed. %d\n", ret);68return ret;69}7071buf[0] = r100.tw_sm_c_100.data1_reg;7273if (len > 0) {74r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);75deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);7677/* there is at least one more byte, otherwise we wouldn't be here */78buf[1] = r104.tw_sm_c_104.data2_reg;79if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;80if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;81}82return 0;83}8485static int flexcop_i2c_write4(struct flexcop_device *fc,86flexcop_ibi_value r100, u8 *buf)87{88flexcop_ibi_value r104;89int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */90r104.raw = 0;9192/* there is at least one byte, otherwise we wouldn't be here */93r100.tw_sm_c_100.data1_reg = buf[0];94r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;95r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;96r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;9798deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);99100/* write the additional i2c data before doing the actual i2c operation */101fc->write_ibi_reg(fc, tw_sm_c_104, r104);102return flexcop_i2c_operation(fc, &r100);103}104105int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,106flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)107{108int ret;109110#ifdef DUMP_I2C_MESSAGES111int i;112#endif113114u16 bytes_to_transfer;115flexcop_ibi_value r100;116117deb_i2c("op = %d\n",op);118r100.raw = 0;119r100.tw_sm_c_100.chipaddr = chipaddr;120r100.tw_sm_c_100.twoWS_rw = op;121r100.tw_sm_c_100.twoWS_port_reg = i2c->port;122123#ifdef DUMP_I2C_MESSAGES124printk(KERN_DEBUG "%d ", i2c->port);125if (op == FC_READ)126printk("rd(");127else128printk("wr(");129printk("%02x): %02x ", chipaddr, addr);130#endif131132/* in that case addr is the only value ->133* we write it twice as baseaddr and val0134* BBTI is doing it like that for ISL6421 at least */135if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {136buf = &addr;137len = 1;138}139140while (len != 0) {141bytes_to_transfer = len > 4 ? 4 : len;142143r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;144r100.tw_sm_c_100.baseaddr = addr;145146if (op == FC_READ)147ret = flexcop_i2c_read4(i2c, r100, buf);148else149ret = flexcop_i2c_write4(i2c->fc, r100, buf);150151#ifdef DUMP_I2C_MESSAGES152for (i = 0; i < bytes_to_transfer; i++)153printk("%02x ", buf[i]);154#endif155156if (ret < 0)157return ret;158159buf += bytes_to_transfer;160addr += bytes_to_transfer;161len -= bytes_to_transfer;162}163164#ifdef DUMP_I2C_MESSAGES165printk("\n");166#endif167168return 0;169}170/* exported for PCI i2c */171EXPORT_SYMBOL(flexcop_i2c_request);172173/* master xfer callback for demodulator */174static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,175struct i2c_msg msgs[], int num)176{177struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);178int i, ret = 0;179180/* Some drivers use 1 byte or 0 byte reads as probes, which this181* driver doesn't support. These probes will always fail, so this182* hack makes them always succeed. If one knew how, it would of183* course be better to actually do the read. */184if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)185return 1;186187if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))188return -ERESTARTSYS;189190for (i = 0; i < num; i++) {191/* reading */192if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {193ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,194msgs[i].buf[0], msgs[i+1].buf,195msgs[i+1].len);196i++; /* skip the following message */197} else /* writing */198ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,199msgs[i].buf[0], &msgs[i].buf[1],200msgs[i].len - 1);201if (ret < 0) {202deb_i2c("i2c master_xfer failed");203break;204}205}206207mutex_unlock(&i2c->fc->i2c_mutex);208209if (ret == 0)210ret = num;211return ret;212}213214static u32 flexcop_i2c_func(struct i2c_adapter *adapter)215{216return I2C_FUNC_I2C;217}218219static struct i2c_algorithm flexcop_algo = {220.master_xfer = flexcop_master_xfer,221.functionality = flexcop_i2c_func,222};223224int flexcop_i2c_init(struct flexcop_device *fc)225{226int ret;227mutex_init(&fc->i2c_mutex);228229fc->fc_i2c_adap[0].fc = fc;230fc->fc_i2c_adap[1].fc = fc;231fc->fc_i2c_adap[2].fc = fc;232fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;233fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;234fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;235236strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",237sizeof(fc->fc_i2c_adap[0].i2c_adap.name));238strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",239sizeof(fc->fc_i2c_adap[1].i2c_adap.name));240strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",241sizeof(fc->fc_i2c_adap[2].i2c_adap.name));242243i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);244i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);245i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);246247fc->fc_i2c_adap[0].i2c_adap.algo =248fc->fc_i2c_adap[1].i2c_adap.algo =249fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;250fc->fc_i2c_adap[0].i2c_adap.algo_data =251fc->fc_i2c_adap[1].i2c_adap.algo_data =252fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;253fc->fc_i2c_adap[0].i2c_adap.dev.parent =254fc->fc_i2c_adap[1].i2c_adap.dev.parent =255fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;256257ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);258if (ret < 0)259return ret;260261ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);262if (ret < 0)263goto adap_1_failed;264265ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);266if (ret < 0)267goto adap_2_failed;268269fc->init_state |= FC_STATE_I2C_INIT;270return 0;271272adap_2_failed:273i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);274adap_1_failed:275i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);276return ret;277}278279void flexcop_i2c_exit(struct flexcop_device *fc)280{281if (fc->init_state & FC_STATE_I2C_INIT) {282i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);283i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);284i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);285}286fc->init_state &= ~FC_STATE_I2C_INIT;287}288289290