aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2008-04-22 16:16:47 -0400
committerJean Delvare <khali@hyperion.delvare>2008-04-22 16:16:47 -0400
commit4dd39bb12f5b9f0d9a98f29071dc1c51e9306954 (patch)
tree0cab698b36a97a4a73211d6f6370efd2296337ca /drivers/i2c
parent4c03f68fc4ab902353336b6b0c6933617821cf70 (diff)
i2c-bfin-twi: Add repeat start feature to avoid break of a bundle of i2c master xfer operation
- Create a new mode TWI_I2C_MODE_REPEAT. - No change to smbus operation. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c185
1 files changed, 114 insertions, 71 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 7dbdaeb707a9..86956a8f0ae5 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -39,9 +39,10 @@
39#define POLL_TIMEOUT (2 * HZ) 39#define POLL_TIMEOUT (2 * HZ)
40 40
41/* SMBus mode*/ 41/* SMBus mode*/
42#define TWI_I2C_MODE_STANDARD 0x01 42#define TWI_I2C_MODE_STANDARD 1
43#define TWI_I2C_MODE_STANDARDSUB 0x02 43#define TWI_I2C_MODE_STANDARDSUB 2
44#define TWI_I2C_MODE_COMBINED 0x04 44#define TWI_I2C_MODE_COMBINED 3
45#define TWI_I2C_MODE_REPEAT 4
45 46
46struct bfin_twi_iface { 47struct bfin_twi_iface {
47 int irq; 48 int irq;
@@ -58,6 +59,9 @@ struct bfin_twi_iface {
58 struct timer_list timeout_timer; 59 struct timer_list timeout_timer;
59 struct i2c_adapter adap; 60 struct i2c_adapter adap;
60 struct completion complete; 61 struct completion complete;
62 struct i2c_msg *pmsg;
63 int msg_num;
64 int cur_msg;
61}; 65};
62 66
63static struct bfin_twi_iface twi_iface; 67static struct bfin_twi_iface twi_iface;
@@ -76,12 +80,16 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
76 /* start receive immediately after complete sending in 80 /* start receive immediately after complete sending in
77 * combine mode. 81 * combine mode.
78 */ 82 */
79 else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { 83 else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
80 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() 84 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
81 | MDIR | RSTART); 85 | MDIR | RSTART);
82 } else if (iface->manual_stop) 86 else if (iface->manual_stop)
83 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() 87 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
84 | STOP); 88 | STOP);
89 else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
90 iface->cur_msg+1 < iface->msg_num)
91 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
92 | RSTART);
85 SSYNC(); 93 SSYNC();
86 /* Clear status */ 94 /* Clear status */
87 bfin_write_TWI_INT_STAT(XMTSERV); 95 bfin_write_TWI_INT_STAT(XMTSERV);
@@ -108,6 +116,11 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
108 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() 116 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
109 | STOP); 117 | STOP);
110 SSYNC(); 118 SSYNC();
119 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
120 iface->cur_msg+1 < iface->msg_num) {
121 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
122 | RSTART);
123 SSYNC();
111 } 124 }
112 /* Clear interrupt source */ 125 /* Clear interrupt source */
113 bfin_write_TWI_INT_STAT(RCVSERV); 126 bfin_write_TWI_INT_STAT(RCVSERV);
@@ -119,7 +132,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
119 bfin_write_TWI_MASTER_STAT(0x3e); 132 bfin_write_TWI_MASTER_STAT(0x3e);
120 bfin_write_TWI_MASTER_CTL(0); 133 bfin_write_TWI_MASTER_CTL(0);
121 SSYNC(); 134 SSYNC();
122 iface->result = -1; 135 iface->result = -EIO;
123 /* if both err and complete int stats are set, return proper 136 /* if both err and complete int stats are set, return proper
124 * results. 137 * results.
125 */ 138 */
@@ -170,6 +183,42 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
170 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | 183 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
171 MEN | MDIR); 184 MEN | MDIR);
172 SSYNC(); 185 SSYNC();
186 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
187 iface->cur_msg+1 < iface->msg_num) {
188 iface->cur_msg++;
189 iface->transPtr = iface->pmsg[iface->cur_msg].buf;
190 iface->writeNum = iface->readNum =
191 iface->pmsg[iface->cur_msg].len;
192 /* Set Transmit device address */
193 bfin_write_TWI_MASTER_ADDR(
194 iface->pmsg[iface->cur_msg].addr);
195 if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD)
196 iface->read_write = I2C_SMBUS_READ;
197 else {
198 iface->read_write = I2C_SMBUS_WRITE;
199 /* Transmit first data */
200 if (iface->writeNum > 0) {
201 bfin_write_TWI_XMT_DATA8(
202 *(iface->transPtr++));
203 iface->writeNum--;
204 SSYNC();
205 }
206 }
207
208 if (iface->pmsg[iface->cur_msg].len <= 255)
209 bfin_write_TWI_MASTER_CTL(
210 iface->pmsg[iface->cur_msg].len << 6);
211 else {
212 bfin_write_TWI_MASTER_CTL(0xff << 6);
213 iface->manual_stop = 1;
214 }
215 /* remove restart bit and enable master receive */
216 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
217 ~RSTART);
218 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
219 MEN | ((iface->read_write == I2C_SMBUS_READ) ?
220 MDIR : 0));
221 SSYNC();
173 } else { 222 } else {
174 iface->result = 1; 223 iface->result = 1;
175 bfin_write_TWI_INT_MASK(0); 224 bfin_write_TWI_INT_MASK(0);
@@ -221,7 +270,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
221{ 270{
222 struct bfin_twi_iface *iface = adap->algo_data; 271 struct bfin_twi_iface *iface = adap->algo_data;
223 struct i2c_msg *pmsg; 272 struct i2c_msg *pmsg;
224 int i, ret;
225 int rc = 0; 273 int rc = 0;
226 274
227 if (!(bfin_read_TWI_CONTROL() & TWI_ENA)) 275 if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
@@ -231,81 +279,76 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
231 yield(); 279 yield();
232 } 280 }
233 281
234 ret = 0; 282 iface->pmsg = msgs;
235 for (i = 0; rc >= 0 && i < num; i++) { 283 iface->msg_num = num;
236 pmsg = &msgs[i]; 284 iface->cur_msg = 0;
237 if (pmsg->flags & I2C_M_TEN) {
238 dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
239 "not supported !\n");
240 rc = -EINVAL;
241 break;
242 }
243 285
244 iface->cur_mode = TWI_I2C_MODE_STANDARD; 286 pmsg = &msgs[0];
245 iface->manual_stop = 0; 287 if (pmsg->flags & I2C_M_TEN) {
246 iface->transPtr = pmsg->buf; 288 dev_err(&adap->dev, "10 bits addr not supported!\n");
247 iface->writeNum = iface->readNum = pmsg->len; 289 return -EINVAL;
248 iface->result = 0; 290 }
249 iface->timeout_count = 10;
250 /* Set Transmit device address */
251 bfin_write_TWI_MASTER_ADDR(pmsg->addr);
252
253 /* FIFO Initiation. Data in FIFO should be
254 * discarded before start a new operation.
255 */
256 bfin_write_TWI_FIFO_CTL(0x3);
257 SSYNC();
258 bfin_write_TWI_FIFO_CTL(0);
259 SSYNC();
260 291
261 if (pmsg->flags & I2C_M_RD) 292 iface->cur_mode = TWI_I2C_MODE_REPEAT;
262 iface->read_write = I2C_SMBUS_READ; 293 iface->manual_stop = 0;
263 else { 294 iface->transPtr = pmsg->buf;
264 iface->read_write = I2C_SMBUS_WRITE; 295 iface->writeNum = iface->readNum = pmsg->len;
265 /* Transmit first data */ 296 iface->result = 0;
266 if (iface->writeNum > 0) { 297 iface->timeout_count = 10;
267 bfin_write_TWI_XMT_DATA8(*(iface->transPtr++)); 298 /* Set Transmit device address */
268 iface->writeNum--; 299 bfin_write_TWI_MASTER_ADDR(pmsg->addr);
269 SSYNC(); 300
270 } 301 /* FIFO Initiation. Data in FIFO should be
302 * discarded before start a new operation.
303 */
304 bfin_write_TWI_FIFO_CTL(0x3);
305 SSYNC();
306 bfin_write_TWI_FIFO_CTL(0);
307 SSYNC();
308
309 if (pmsg->flags & I2C_M_RD)
310 iface->read_write = I2C_SMBUS_READ;
311 else {
312 iface->read_write = I2C_SMBUS_WRITE;
313 /* Transmit first data */
314 if (iface->writeNum > 0) {
315 bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
316 iface->writeNum--;
317 SSYNC();
271 } 318 }
319 }
272 320
273 /* clear int stat */ 321 /* clear int stat */
274 bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV); 322 bfin_write_TWI_INT_STAT(MERR | MCOMP | XMTSERV | RCVSERV);
275 323
276 /* Interrupt mask . Enable XMT, RCV interrupt */ 324 /* Interrupt mask . Enable XMT, RCV interrupt */
277 bfin_write_TWI_INT_MASK(MCOMP | MERR | 325 bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
278 ((iface->read_write == I2C_SMBUS_READ)? 326 SSYNC();
279 RCVSERV : XMTSERV));
280 SSYNC();
281 327
282 if (pmsg->len > 0 && pmsg->len <= 255) 328 if (pmsg->len <= 255)
283 bfin_write_TWI_MASTER_CTL(pmsg->len << 6); 329 bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
284 else if (pmsg->len > 255) { 330 else {
285 bfin_write_TWI_MASTER_CTL(0xff << 6); 331 bfin_write_TWI_MASTER_CTL(0xff << 6);
286 iface->manual_stop = 1; 332 iface->manual_stop = 1;
287 } else 333 }
288 break;
289 334
290 iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; 335 iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
291 add_timer(&iface->timeout_timer); 336 add_timer(&iface->timeout_timer);
292 337
293 /* Master enable */ 338 /* Master enable */
294 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | 339 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
295 ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | 340 ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
296 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); 341 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
297 SSYNC(); 342 SSYNC();
298 343
299 wait_for_completion(&iface->complete); 344 wait_for_completion(&iface->complete);
300 345
301 rc = iface->result; 346 rc = iface->result;
302 if (rc == 1)
303 ret++;
304 else if (rc == -1)
305 break;
306 }
307 347
308 return ret; 348 if (rc == 1)
349 return num;
350 else
351 return rc;
309} 352}
310 353
311/* 354/*