2 * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
4 * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
6 * see flexcop.c for copyright information.
10 #define FC_MAX_I2C_RETRIES 100000
12 /* #define DUMP_I2C_MESSAGES */
14 static int flexcop_i2c_operation(struct flexcop_device
*fc
, flexcop_ibi_value
*r100
)
19 r100
->tw_sm_c_100
.working_start
= 1;
20 deb_i2c("r100 before: %08x\n",r100
->raw
);
22 fc
->write_ibi_reg(fc
, tw_sm_c_100
, ibi_zero
);
23 fc
->write_ibi_reg(fc
, tw_sm_c_100
, *r100
); /* initiating i2c operation */
25 for (i
= 0; i
< FC_MAX_I2C_RETRIES
; i
++) {
26 r
= fc
->read_ibi_reg(fc
, tw_sm_c_100
);
28 if (!r
.tw_sm_c_100
.no_base_addr_ack_error
) {
29 if (r
.tw_sm_c_100
.st_done
) { /* && !r.tw_sm_c_100.working_start */
31 deb_i2c("i2c success\n");
35 deb_i2c("suffering from an i2c ack_error\n");
39 deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i
);
43 static int flexcop_i2c_read4(struct flexcop_i2c_adapter
*i2c
,
44 flexcop_ibi_value r100
, u8
*buf
)
46 flexcop_ibi_value r104
;
47 int len
= r100
.tw_sm_c_100
.total_bytes
, /* remember total_bytes is buflen-1 */
50 r100
.tw_sm_c_100
.no_base_addr_ack_error
= i2c
->no_base_addr
;
51 ret
= flexcop_i2c_operation(i2c
->fc
, &r100
);
53 deb_i2c("read failed. %d\n", ret
);
57 buf
[0] = r100
.tw_sm_c_100
.data1_reg
;
60 r104
= i2c
->fc
->read_ibi_reg(i2c
->fc
, tw_sm_c_104
);
61 deb_i2c("read: r100: %08x, r104: %08x\n", r100
.raw
, r104
.raw
);
63 /* there is at least one more byte, otherwise we wouldn't be here */
64 buf
[1] = r104
.tw_sm_c_104
.data2_reg
;
65 if (len
> 1) buf
[2] = r104
.tw_sm_c_104
.data3_reg
;
66 if (len
> 2) buf
[3] = r104
.tw_sm_c_104
.data4_reg
;
72 static int flexcop_i2c_write4(struct flexcop_device
*fc
, flexcop_ibi_value r100
, u8
*buf
)
74 flexcop_ibi_value r104
;
75 int len
= r100
.tw_sm_c_100
.total_bytes
; /* remember total_bytes is buflen-1 */
78 /* there is at least one byte, otherwise we wouldn't be here */
79 r100
.tw_sm_c_100
.data1_reg
= buf
[0];
81 r104
.tw_sm_c_104
.data2_reg
= len
> 0 ? buf
[1] : 0;
82 r104
.tw_sm_c_104
.data3_reg
= len
> 1 ? buf
[2] : 0;
83 r104
.tw_sm_c_104
.data4_reg
= len
> 2 ? buf
[3] : 0;
85 deb_i2c("write: r100: %08x, r104: %08x\n", r100
.raw
, r104
.raw
);
87 /* write the additional i2c data before doing the actual i2c operation */
88 fc
->write_ibi_reg(fc
, tw_sm_c_104
, r104
);
89 return flexcop_i2c_operation(fc
, &r100
);
92 int flexcop_i2c_request(struct flexcop_i2c_adapter
*i2c
,
93 flexcop_access_op_t op
, u8 chipaddr
, u8 addr
, u8
*buf
, u16 len
)
97 #ifdef DUMP_I2C_MESSAGES
101 u16 bytes_to_transfer
;
102 flexcop_ibi_value r100
;
104 deb_i2c("op = %d\n",op
);
106 r100
.tw_sm_c_100
.chipaddr
= chipaddr
;
107 r100
.tw_sm_c_100
.twoWS_rw
= op
;
108 r100
.tw_sm_c_100
.twoWS_port_reg
= i2c
->port
;
110 #ifdef DUMP_I2C_MESSAGES
111 printk(KERN_DEBUG
"%d ", i2c
->port
);
117 printk("%02x): %02x ", chipaddr
, addr
);
120 /* in that case addr is the only value ->
121 * we write it twice as baseaddr and val0
122 * BBTI is doing it like that for ISL6421 at least */
123 if (i2c
->no_base_addr
&& len
== 0 && op
== FC_WRITE
) {
129 bytes_to_transfer
= len
> 4 ? 4 : len
;
131 r100
.tw_sm_c_100
.total_bytes
= bytes_to_transfer
- 1;
132 r100
.tw_sm_c_100
.baseaddr
= addr
;
135 ret
= flexcop_i2c_read4(i2c
, r100
, buf
);
137 ret
= flexcop_i2c_write4(i2c
->fc
, r100
, buf
);
139 #ifdef DUMP_I2C_MESSAGES
140 for (i
= 0; i
< bytes_to_transfer
; i
++)
141 printk("%02x ", buf
[i
]);
147 buf
+= bytes_to_transfer
;
148 addr
+= bytes_to_transfer
;
149 len
-= bytes_to_transfer
;
152 #ifdef DUMP_I2C_MESSAGES
158 /* exported for PCI i2c */
159 EXPORT_SYMBOL(flexcop_i2c_request
);
161 /* master xfer callback for demodulator */
162 static int flexcop_master_xfer(struct i2c_adapter
*i2c_adap
, struct i2c_msg msgs
[], int num
)
164 struct flexcop_i2c_adapter
*i2c
= i2c_get_adapdata(i2c_adap
);
167 /* Some drivers use 1 byte or 0 byte reads as probes, which this
168 * driver doesn't support. These probes will always fail, so this
169 * hack makes them always succeed. If one knew how, it would of
170 * course be better to actually do the read. */
171 if (num
== 1 && msgs
[0].flags
== I2C_M_RD
&& msgs
[0].len
<= 1)
174 if (mutex_lock_interruptible(&i2c
->fc
->i2c_mutex
))
177 for (i
= 0; i
< num
; i
++) {
179 if (i
+1 < num
&& (msgs
[i
+1].flags
== I2C_M_RD
)) {
180 ret
= i2c
->fc
->i2c_request(i2c
, FC_READ
, msgs
[i
].addr
,
181 msgs
[i
].buf
[0], msgs
[i
+1].buf
, msgs
[i
+1].len
);
182 i
++; /* skip the following message */
184 ret
= i2c
->fc
->i2c_request(i2c
, FC_WRITE
, msgs
[i
].addr
,
185 msgs
[i
].buf
[0], &msgs
[i
].buf
[1],
188 err("i2c master_xfer failed");
193 mutex_unlock(&i2c
->fc
->i2c_mutex
);
200 static u32
flexcop_i2c_func(struct i2c_adapter
*adapter
)
205 static struct i2c_algorithm flexcop_algo
= {
206 .master_xfer
= flexcop_master_xfer
,
207 .functionality
= flexcop_i2c_func
,
210 int flexcop_i2c_init(struct flexcop_device
*fc
)
214 mutex_init(&fc
->i2c_mutex
);
216 fc
->fc_i2c_adap
[0].fc
= fc
;
217 fc
->fc_i2c_adap
[1].fc
= fc
;
218 fc
->fc_i2c_adap
[2].fc
= fc
;
220 fc
->fc_i2c_adap
[0].port
= FC_I2C_PORT_DEMOD
;
221 fc
->fc_i2c_adap
[1].port
= FC_I2C_PORT_EEPROM
;
222 fc
->fc_i2c_adap
[2].port
= FC_I2C_PORT_TUNER
;
224 strncpy(fc
->fc_i2c_adap
[0].i2c_adap
.name
,
225 "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE
);
226 strncpy(fc
->fc_i2c_adap
[1].i2c_adap
.name
,
227 "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE
);
228 strncpy(fc
->fc_i2c_adap
[2].i2c_adap
.name
,
229 "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE
);
231 i2c_set_adapdata(&fc
->fc_i2c_adap
[0].i2c_adap
, &fc
->fc_i2c_adap
[0]);
232 i2c_set_adapdata(&fc
->fc_i2c_adap
[1].i2c_adap
, &fc
->fc_i2c_adap
[1]);
233 i2c_set_adapdata(&fc
->fc_i2c_adap
[2].i2c_adap
, &fc
->fc_i2c_adap
[2]);
235 fc
->fc_i2c_adap
[0].i2c_adap
.class =
236 fc
->fc_i2c_adap
[1].i2c_adap
.class =
237 fc
->fc_i2c_adap
[2].i2c_adap
.class = I2C_CLASS_TV_DIGITAL
;
238 fc
->fc_i2c_adap
[0].i2c_adap
.algo
=
239 fc
->fc_i2c_adap
[1].i2c_adap
.algo
=
240 fc
->fc_i2c_adap
[2].i2c_adap
.algo
= &flexcop_algo
;
241 fc
->fc_i2c_adap
[0].i2c_adap
.algo_data
=
242 fc
->fc_i2c_adap
[1].i2c_adap
.algo_data
=
243 fc
->fc_i2c_adap
[2].i2c_adap
.algo_data
= NULL
;
244 fc
->fc_i2c_adap
[0].i2c_adap
.dev
.parent
=
245 fc
->fc_i2c_adap
[1].i2c_adap
.dev
.parent
=
246 fc
->fc_i2c_adap
[2].i2c_adap
.dev
.parent
= fc
->dev
;
248 ret
= i2c_add_adapter(&fc
->fc_i2c_adap
[0].i2c_adap
);
252 ret
= i2c_add_adapter(&fc
->fc_i2c_adap
[1].i2c_adap
);
256 ret
= i2c_add_adapter(&fc
->fc_i2c_adap
[2].i2c_adap
);
260 fc
->init_state
|= FC_STATE_I2C_INIT
;
264 i2c_del_adapter(&fc
->fc_i2c_adap
[1].i2c_adap
);
266 i2c_del_adapter(&fc
->fc_i2c_adap
[0].i2c_adap
);
271 void flexcop_i2c_exit(struct flexcop_device
*fc
)
273 if (fc
->init_state
& FC_STATE_I2C_INIT
) {
274 i2c_del_adapter(&fc
->fc_i2c_adap
[2].i2c_adap
);
275 i2c_del_adapter(&fc
->fc_i2c_adap
[1].i2c_adap
);
276 i2c_del_adapter(&fc
->fc_i2c_adap
[0].i2c_adap
);
279 fc
->init_state
&= ~FC_STATE_I2C_INIT
;