aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/b2c2/flexcop-i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/b2c2/flexcop-i2c.c')
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index 736251f393c2..be4266d4ae91 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -9,9 +9,9 @@
9 9
10#define FC_MAX_I2C_RETRIES 100000 10#define FC_MAX_I2C_RETRIES 100000
11 11
12static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100, int max_ack_errors) 12static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
13{ 13{
14 int i,ack_errors = 0; 14 int i;
15 flexcop_ibi_value r; 15 flexcop_ibi_value r;
16 16
17 r100->tw_sm_c_100.working_start = 1; 17 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
31 } 31 }
32 } else { 32 } else {
33 deb_i2c("suffering from an i2c ack_error\n"); 33 deb_i2c("suffering from an i2c ack_error\n");
34 if (++ack_errors >= max_ack_errors) 34 return -EREMOTEIO;
35 break;
36
37 fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
38 fc->write_ibi_reg(fc, tw_sm_c_100, *r100);
39 } 35 }
40 } 36 }
41 deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); 37 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,
48 int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ 44 int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
49 ret; 45 ret;
50 46
51 if ((ret = flexcop_i2c_operation(fc,&r100,30)) != 0) 47 if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
52 return ret; 48 /* The Cablestar needs a different kind of i2c-transfer (does not
53 49 * support "Repeat Start"):
54 r104 = fc->read_ibi_reg(fc,tw_sm_c_104); 50 * wait for the ACK failure,
55 51 * and do a subsequent read with the Bit 30 enabled
56 deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw); 52 */
53 r100.tw_sm_c_100.no_base_addr_ack_error = 1;
54 if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
55 deb_i2c("no_base_addr read failed. %d\n",ret);
56 return ret;
57 }
58 }
57 59
58 /* there is at least one byte, otherwise we wouldn't be here */
59 buf[0] = r100.tw_sm_c_100.data1_reg; 60 buf[0] = r100.tw_sm_c_100.data1_reg;
60 61
61 if (len > 0) buf[1] = r104.tw_sm_c_104.data2_reg; 62 if (len > 0) {
62 if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; 63 r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
63 if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; 64 deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
65
66 /* there is at least one more byte, otherwise we wouldn't be here */
67 buf[1] = r104.tw_sm_c_104.data2_reg;
68 if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
69 if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
70 }
64 71
65 return 0; 72 return 0;
66} 73}
@@ -82,9 +89,45 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
82 89
83 /* write the additional i2c data before doing the actual i2c operation */ 90 /* write the additional i2c data before doing the actual i2c operation */
84 fc->write_ibi_reg(fc,tw_sm_c_104,r104); 91 fc->write_ibi_reg(fc,tw_sm_c_104,r104);
92 return flexcop_i2c_operation(fc,&r100);
93}
94
95int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
96 flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
97{
98 int ret;
99 u16 bytes_to_transfer;
100 flexcop_ibi_value r100;
101
102 deb_i2c("op = %d\n",op);
103 r100.raw = 0;
104 r100.tw_sm_c_100.chipaddr = chipaddr;
105 r100.tw_sm_c_100.twoWS_rw = op;
106 r100.tw_sm_c_100.twoWS_port_reg = port;
107
108 while (len != 0) {
109 bytes_to_transfer = len > 4 ? 4 : len;
85 110
86 return flexcop_i2c_operation(fc,&r100,30); 111 r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
112 r100.tw_sm_c_100.baseaddr = addr;
113
114 if (op == FC_READ)
115 ret = flexcop_i2c_read4(fc, r100, buf);
116 else
117 ret = flexcop_i2c_write4(fc,r100, buf);
118
119 if (ret < 0)
120 return ret;
121
122 buf += bytes_to_transfer;
123 addr += bytes_to_transfer;
124 len -= bytes_to_transfer;
125 };
126
127 return 0;
87} 128}
129/* exported for PCI i2c */
130EXPORT_SYMBOL(flexcop_i2c_request);
88 131
89/* master xfer callback for demodulator */ 132/* master xfer callback for demodulator */
90static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) 133static 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
123 return ret; 166 return ret;
124} 167}
125 168
126int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
127 flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
128{
129 int ret;
130 u16 bytes_to_transfer;
131 flexcop_ibi_value r100;
132
133 deb_i2c("op = %d\n",op);
134 r100.raw = 0;
135 r100.tw_sm_c_100.chipaddr = chipaddr;
136 r100.tw_sm_c_100.twoWS_rw = op;
137 r100.tw_sm_c_100.twoWS_port_reg = port;
138
139 while (len != 0) {
140 bytes_to_transfer = len > 4 ? 4 : len;
141
142 r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
143 r100.tw_sm_c_100.baseaddr = addr;
144
145 if (op == FC_READ)
146 ret = flexcop_i2c_read4(fc, r100, buf);
147 else
148 ret = flexcop_i2c_write4(fc,r100, buf);
149
150 if (ret < 0)
151 return ret;
152
153 buf += bytes_to_transfer;
154 addr += bytes_to_transfer;
155 len -= bytes_to_transfer;
156 };
157
158 return 0;
159}
160/* exported for PCI i2c */
161EXPORT_SYMBOL(flexcop_i2c_request);
162
163static u32 flexcop_i2c_func(struct i2c_adapter *adapter) 169static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
164{ 170{
165 return I2C_FUNC_I2C; 171 return I2C_FUNC_I2C;