Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdc78001 authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds
Browse files

[PATCH] dvb: flexcop: i2c read fixes



rewrote the i2c-reading-part (no more ack-error ignoring, which was inherited
from the skystar2-driver)

Signed-off-by: default avatarPatrick Boettcher <pb@linuxtv.org>
Signed-off-by: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c6ee197c
Loading
Loading
Loading
Loading
+61 −55
Original line number Original line Diff line number Diff line
@@ -9,9 +9,9 @@


#define FC_MAX_I2C_RETRIES 100000
#define FC_MAX_I2C_RETRIES 100000


static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100, int max_ack_errors)
static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
{
{
	int i,ack_errors = 0;
	int i;
	flexcop_ibi_value r;
	flexcop_ibi_value r;


	r100->tw_sm_c_100.working_start = 1;
	r100->tw_sm_c_100.working_start = 1;
@@ -31,11 +31,7 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
			}
			}
		} else {
		} else {
			deb_i2c("suffering from an i2c ack_error\n");
			deb_i2c("suffering from an i2c ack_error\n");
			if (++ack_errors >= max_ack_errors)
			return -EREMOTEIO;
				break;

			fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
			fc->write_ibi_reg(fc, tw_sm_c_100, *r100);
		}
		}
	}
	}
	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i);
	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i);
@@ -48,19 +44,30 @@ static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100,
	int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
	int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
		ret;
		ret;


	if ((ret = flexcop_i2c_operation(fc,&r100,30)) != 0)
	if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
		/* The Cablestar needs a different kind of i2c-transfer (does not
		 * support "Repeat Start"):
		 * wait for the ACK failure,
		 * and do a subsequent read with the Bit 30 enabled
		 */
		r100.tw_sm_c_100.no_base_addr_ack_error = 1;
		if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
			deb_i2c("no_base_addr read failed. %d\n",ret);
			return ret;
			return ret;
		}
	}


	r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
	buf[0] = r100.tw_sm_c_100.data1_reg;


	if (len > 0) {
		r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
		deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
		deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);


	/* there is at least one byte, otherwise we wouldn't be here */
		/* there is at least one more byte, otherwise we wouldn't be here */
	buf[0] = r100.tw_sm_c_100.data1_reg;
		buf[1] = r104.tw_sm_c_104.data2_reg;

	if (len > 0) buf[1] = r104.tw_sm_c_104.data2_reg;
		if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
		if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
		if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
		if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
	}


	return 0;
	return 0;
}
}
@@ -82,9 +89,45 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,


	/* write the additional i2c data before doing the actual i2c operation */
	/* write the additional i2c data before doing the actual i2c operation */
	fc->write_ibi_reg(fc,tw_sm_c_104,r104);
	fc->write_ibi_reg(fc,tw_sm_c_104,r104);
	return flexcop_i2c_operation(fc,&r100);
}

int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
		flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
{
	int ret;
	u16 bytes_to_transfer;
	flexcop_ibi_value r100;


	return flexcop_i2c_operation(fc,&r100,30);
	deb_i2c("op = %d\n",op);
	r100.raw = 0;
	r100.tw_sm_c_100.chipaddr = chipaddr;
	r100.tw_sm_c_100.twoWS_rw = op;
	r100.tw_sm_c_100.twoWS_port_reg = port;

	while (len != 0) {
		bytes_to_transfer = len > 4 ? 4 : len;

		r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
		r100.tw_sm_c_100.baseaddr = addr;

		if (op == FC_READ)
			ret = flexcop_i2c_read4(fc, r100, buf);
		else
			ret = flexcop_i2c_write4(fc,r100, buf);

		if (ret < 0)
			return ret;

		buf  += bytes_to_transfer;
		addr += bytes_to_transfer;
		len  -= bytes_to_transfer;
	};

	return 0;
}
}
/* exported for PCI i2c */
EXPORT_SYMBOL(flexcop_i2c_request);


/* master xfer callback for demodulator */
/* master xfer callback for demodulator */
static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
@@ -123,43 +166,6 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
	return ret;
	return ret;
}
}


int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
		flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
{
	int ret;
	u16 bytes_to_transfer;
	flexcop_ibi_value r100;

	deb_i2c("op = %d\n",op);
	r100.raw = 0;
	r100.tw_sm_c_100.chipaddr = chipaddr;
	r100.tw_sm_c_100.twoWS_rw = op;
	r100.tw_sm_c_100.twoWS_port_reg = port;

	while (len != 0) {
		bytes_to_transfer = len > 4 ? 4 : len;

		r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
		r100.tw_sm_c_100.baseaddr = addr;

		if (op == FC_READ)
			ret = flexcop_i2c_read4(fc, r100, buf);
		else
			ret = flexcop_i2c_write4(fc,r100, buf);

		if (ret < 0)
			return ret;

		buf  += bytes_to_transfer;
		addr += bytes_to_transfer;
		len  -= bytes_to_transfer;
	};

	return 0;
}
/* exported for PCI i2c */
EXPORT_SYMBOL(flexcop_i2c_request);

static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
{
{
	return I2C_FUNC_I2C;
	return I2C_FUNC_I2C;
+2 −1
Original line number Original line Diff line number Diff line
@@ -692,9 +692,10 @@ typedef enum {
	wan_ctrl_reg_71c    = 0x71c,
	wan_ctrl_reg_71c    = 0x71c,
} flexcop_ibi_register;
} flexcop_ibi_register;


#define flexcop_set_ibi_value(reg,attr,val) \
#define flexcop_set_ibi_value(reg,attr,val) { \
	flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
	flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
	v.reg.attr = val; \
	v.reg.attr = val; \
	fc->write_ibi_reg(fc,reg,v); \
	fc->write_ibi_reg(fc,reg,v); \
}


#endif
#endif
+0 −4
Original line number Original line Diff line number Diff line
@@ -184,10 +184,6 @@ static void flexcop_reset(struct flexcop_device *fc)
	fc->write_ibi_reg(fc,misc_204,v204);
	fc->write_ibi_reg(fc,misc_204,v204);
	v204.misc_204.Per_reset_sig = 1;
	v204.misc_204.Per_reset_sig = 1;
	fc->write_ibi_reg(fc,misc_204,v204);
	fc->write_ibi_reg(fc,misc_204,v204);

/*	v208.raw = 0;
	v208.ctrl_208.Null_filter_sig = 1;
	fc->write_ibi_reg(fc,ctrl_208,v208);*/
}
}


struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)