diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-bfin-twi.c')
-rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 168 |
1 files changed, 78 insertions, 90 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index f1e14dd590c9..fb26e5c67515 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <asm/portmux.h> | 25 | #include <asm/portmux.h> |
26 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | 27 | ||
28 | #define POLL_TIMEOUT (2 * HZ) | ||
29 | |||
30 | /* SMBus mode*/ | 28 | /* SMBus mode*/ |
31 | #define TWI_I2C_MODE_STANDARD 1 | 29 | #define TWI_I2C_MODE_STANDARD 1 |
32 | #define TWI_I2C_MODE_STANDARDSUB 2 | 30 | #define TWI_I2C_MODE_STANDARDSUB 2 |
@@ -44,8 +42,6 @@ struct bfin_twi_iface { | |||
44 | int cur_mode; | 42 | int cur_mode; |
45 | int manual_stop; | 43 | int manual_stop; |
46 | int result; | 44 | int result; |
47 | int timeout_count; | ||
48 | struct timer_list timeout_timer; | ||
49 | struct i2c_adapter adap; | 45 | struct i2c_adapter adap; |
50 | struct completion complete; | 46 | struct completion complete; |
51 | struct i2c_msg *pmsg; | 47 | struct i2c_msg *pmsg; |
@@ -85,14 +81,15 @@ static const u16 pin_req[2][3] = { | |||
85 | {P_TWI1_SCL, P_TWI1_SDA, 0}, | 81 | {P_TWI1_SCL, P_TWI1_SDA, 0}, |
86 | }; | 82 | }; |
87 | 83 | ||
88 | static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | 84 | static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, |
85 | unsigned short twi_int_status) | ||
89 | { | 86 | { |
90 | unsigned short twi_int_status = read_INT_STAT(iface); | ||
91 | unsigned short mast_stat = read_MASTER_STAT(iface); | 87 | unsigned short mast_stat = read_MASTER_STAT(iface); |
92 | 88 | ||
93 | if (twi_int_status & XMTSERV) { | 89 | if (twi_int_status & XMTSERV) { |
94 | /* Transmit next data */ | 90 | /* Transmit next data */ |
95 | if (iface->writeNum > 0) { | 91 | if (iface->writeNum > 0) { |
92 | SSYNC(); | ||
96 | write_XMT_DATA8(iface, *(iface->transPtr++)); | 93 | write_XMT_DATA8(iface, *(iface->transPtr++)); |
97 | iface->writeNum--; | 94 | iface->writeNum--; |
98 | } | 95 | } |
@@ -114,10 +111,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
114 | write_MASTER_CTL(iface, | 111 | write_MASTER_CTL(iface, |
115 | (read_MASTER_CTL(iface) | RSTART) & ~MDIR); | 112 | (read_MASTER_CTL(iface) | RSTART) & ~MDIR); |
116 | } | 113 | } |
117 | SSYNC(); | ||
118 | /* Clear status */ | ||
119 | write_INT_STAT(iface, XMTSERV); | ||
120 | SSYNC(); | ||
121 | } | 114 | } |
122 | if (twi_int_status & RCVSERV) { | 115 | if (twi_int_status & RCVSERV) { |
123 | if (iface->readNum > 0) { | 116 | if (iface->readNum > 0) { |
@@ -139,7 +132,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
139 | } else if (iface->manual_stop) { | 132 | } else if (iface->manual_stop) { |
140 | write_MASTER_CTL(iface, | 133 | write_MASTER_CTL(iface, |
141 | read_MASTER_CTL(iface) | STOP); | 134 | read_MASTER_CTL(iface) | STOP); |
142 | SSYNC(); | ||
143 | } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && | 135 | } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && |
144 | iface->cur_msg + 1 < iface->msg_num) { | 136 | iface->cur_msg + 1 < iface->msg_num) { |
145 | if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) | 137 | if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) |
@@ -148,44 +140,37 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
148 | else | 140 | else |
149 | write_MASTER_CTL(iface, | 141 | write_MASTER_CTL(iface, |
150 | (read_MASTER_CTL(iface) | RSTART) & ~MDIR); | 142 | (read_MASTER_CTL(iface) | RSTART) & ~MDIR); |
151 | SSYNC(); | ||
152 | } | 143 | } |
153 | /* Clear interrupt source */ | ||
154 | write_INT_STAT(iface, RCVSERV); | ||
155 | SSYNC(); | ||
156 | } | 144 | } |
157 | if (twi_int_status & MERR) { | 145 | if (twi_int_status & MERR) { |
158 | write_INT_STAT(iface, MERR); | ||
159 | write_INT_MASK(iface, 0); | 146 | write_INT_MASK(iface, 0); |
160 | write_MASTER_STAT(iface, 0x3e); | 147 | write_MASTER_STAT(iface, 0x3e); |
161 | write_MASTER_CTL(iface, 0); | 148 | write_MASTER_CTL(iface, 0); |
162 | SSYNC(); | ||
163 | iface->result = -EIO; | 149 | iface->result = -EIO; |
164 | /* if both err and complete int stats are set, return proper | 150 | |
165 | * results. | 151 | if (mast_stat & LOSTARB) |
152 | dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); | ||
153 | if (mast_stat & ANAK) | ||
154 | dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); | ||
155 | if (mast_stat & DNAK) | ||
156 | dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); | ||
157 | if (mast_stat & BUFRDERR) | ||
158 | dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); | ||
159 | if (mast_stat & BUFWRERR) | ||
160 | dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); | ||
161 | |||
162 | /* If it is a quick transfer, only address without data, | ||
163 | * not an err, return 1. | ||
166 | */ | 164 | */ |
167 | if (twi_int_status & MCOMP) { | 165 | if (iface->cur_mode == TWI_I2C_MODE_STANDARD && |
168 | write_INT_STAT(iface, MCOMP); | 166 | iface->transPtr == NULL && |
169 | write_INT_MASK(iface, 0); | 167 | (twi_int_status & MCOMP) && (mast_stat & DNAK)) |
170 | write_MASTER_CTL(iface, 0); | 168 | iface->result = 1; |
171 | SSYNC(); | 169 | |
172 | /* If it is a quick transfer, only address bug no data, | ||
173 | * not an err, return 1. | ||
174 | */ | ||
175 | if (iface->writeNum == 0 && (mast_stat & BUFRDERR)) | ||
176 | iface->result = 1; | ||
177 | /* If address not acknowledged return -1, | ||
178 | * else return 0. | ||
179 | */ | ||
180 | else if (!(mast_stat & ANAK)) | ||
181 | iface->result = 0; | ||
182 | } | ||
183 | complete(&iface->complete); | 170 | complete(&iface->complete); |
184 | return; | 171 | return; |
185 | } | 172 | } |
186 | if (twi_int_status & MCOMP) { | 173 | if (twi_int_status & MCOMP) { |
187 | write_INT_STAT(iface, MCOMP); | ||
188 | SSYNC(); | ||
189 | if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { | 174 | if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { |
190 | if (iface->readNum == 0) { | 175 | if (iface->readNum == 0) { |
191 | /* set the read number to 1 and ask for manual | 176 | /* set the read number to 1 and ask for manual |
@@ -207,7 +192,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
207 | /* remove restart bit and enable master receive */ | 192 | /* remove restart bit and enable master receive */ |
208 | write_MASTER_CTL(iface, | 193 | write_MASTER_CTL(iface, |
209 | read_MASTER_CTL(iface) & ~RSTART); | 194 | read_MASTER_CTL(iface) & ~RSTART); |
210 | SSYNC(); | ||
211 | } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && | 195 | } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && |
212 | iface->cur_msg+1 < iface->msg_num) { | 196 | iface->cur_msg+1 < iface->msg_num) { |
213 | iface->cur_msg++; | 197 | iface->cur_msg++; |
@@ -226,7 +210,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
226 | write_XMT_DATA8(iface, | 210 | write_XMT_DATA8(iface, |
227 | *(iface->transPtr++)); | 211 | *(iface->transPtr++)); |
228 | iface->writeNum--; | 212 | iface->writeNum--; |
229 | SSYNC(); | ||
230 | } | 213 | } |
231 | } | 214 | } |
232 | 215 | ||
@@ -244,15 +227,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
244 | /* remove restart bit and enable master receive */ | 227 | /* remove restart bit and enable master receive */ |
245 | write_MASTER_CTL(iface, | 228 | write_MASTER_CTL(iface, |
246 | read_MASTER_CTL(iface) & ~RSTART); | 229 | read_MASTER_CTL(iface) & ~RSTART); |
247 | SSYNC(); | ||
248 | } else { | 230 | } else { |
249 | iface->result = 1; | 231 | iface->result = 1; |
250 | write_INT_MASK(iface, 0); | 232 | write_INT_MASK(iface, 0); |
251 | write_MASTER_CTL(iface, 0); | 233 | write_MASTER_CTL(iface, 0); |
252 | SSYNC(); | ||
253 | complete(&iface->complete); | ||
254 | } | 234 | } |
255 | } | 235 | } |
236 | complete(&iface->complete); | ||
256 | } | 237 | } |
257 | 238 | ||
258 | /* Interrupt handler */ | 239 | /* Interrupt handler */ |
@@ -260,38 +241,26 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) | |||
260 | { | 241 | { |
261 | struct bfin_twi_iface *iface = dev_id; | 242 | struct bfin_twi_iface *iface = dev_id; |
262 | unsigned long flags; | 243 | unsigned long flags; |
244 | unsigned short twi_int_status; | ||
263 | 245 | ||
264 | spin_lock_irqsave(&iface->lock, flags); | 246 | spin_lock_irqsave(&iface->lock, flags); |
265 | del_timer(&iface->timeout_timer); | 247 | while (1) { |
266 | bfin_twi_handle_interrupt(iface); | 248 | twi_int_status = read_INT_STAT(iface); |
267 | spin_unlock_irqrestore(&iface->lock, flags); | 249 | if (!twi_int_status) |
268 | return IRQ_HANDLED; | 250 | break; |
269 | } | 251 | /* Clear interrupt status */ |
270 | 252 | write_INT_STAT(iface, twi_int_status); | |
271 | static void bfin_twi_timeout(unsigned long data) | 253 | bfin_twi_handle_interrupt(iface, twi_int_status); |
272 | { | 254 | SSYNC(); |
273 | struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data; | ||
274 | unsigned long flags; | ||
275 | |||
276 | spin_lock_irqsave(&iface->lock, flags); | ||
277 | bfin_twi_handle_interrupt(iface); | ||
278 | if (iface->result == 0) { | ||
279 | iface->timeout_count--; | ||
280 | if (iface->timeout_count > 0) { | ||
281 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
282 | add_timer(&iface->timeout_timer); | ||
283 | } else { | ||
284 | iface->result = -1; | ||
285 | complete(&iface->complete); | ||
286 | } | ||
287 | } | 255 | } |
288 | spin_unlock_irqrestore(&iface->lock, flags); | 256 | spin_unlock_irqrestore(&iface->lock, flags); |
257 | return IRQ_HANDLED; | ||
289 | } | 258 | } |
290 | 259 | ||
291 | /* | 260 | /* |
292 | * Generic i2c master transfer entrypoint | 261 | * One i2c master transfer |
293 | */ | 262 | */ |
294 | static int bfin_twi_master_xfer(struct i2c_adapter *adap, | 263 | static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, |
295 | struct i2c_msg *msgs, int num) | 264 | struct i2c_msg *msgs, int num) |
296 | { | 265 | { |
297 | struct bfin_twi_iface *iface = adap->algo_data; | 266 | struct bfin_twi_iface *iface = adap->algo_data; |
@@ -319,7 +288,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, | |||
319 | iface->transPtr = pmsg->buf; | 288 | iface->transPtr = pmsg->buf; |
320 | iface->writeNum = iface->readNum = pmsg->len; | 289 | iface->writeNum = iface->readNum = pmsg->len; |
321 | iface->result = 0; | 290 | iface->result = 0; |
322 | iface->timeout_count = 10; | ||
323 | init_completion(&(iface->complete)); | 291 | init_completion(&(iface->complete)); |
324 | /* Set Transmit device address */ | 292 | /* Set Transmit device address */ |
325 | write_MASTER_ADDR(iface, pmsg->addr); | 293 | write_MASTER_ADDR(iface, pmsg->addr); |
@@ -358,30 +326,41 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, | |||
358 | iface->manual_stop = 1; | 326 | iface->manual_stop = 1; |
359 | } | 327 | } |
360 | 328 | ||
361 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
362 | add_timer(&iface->timeout_timer); | ||
363 | |||
364 | /* Master enable */ | 329 | /* Master enable */ |
365 | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | | 330 | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | |
366 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | | 331 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | |
367 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); | 332 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); |
368 | SSYNC(); | 333 | SSYNC(); |
369 | 334 | ||
370 | wait_for_completion(&iface->complete); | 335 | while (!iface->result) { |
371 | 336 | if (!wait_for_completion_timeout(&iface->complete, | |
372 | rc = iface->result; | 337 | adap->timeout)) { |
338 | iface->result = -1; | ||
339 | dev_err(&adap->dev, "master transfer timeout\n"); | ||
340 | } | ||
341 | } | ||
373 | 342 | ||
374 | if (rc == 1) | 343 | if (iface->result == 1) |
375 | return num; | 344 | rc = iface->cur_msg + 1; |
376 | else | 345 | else |
377 | return rc; | 346 | rc = iface->result; |
347 | |||
348 | return rc; | ||
378 | } | 349 | } |
379 | 350 | ||
380 | /* | 351 | /* |
381 | * SMBus type transfer entrypoint | 352 | * Generic i2c master transfer entrypoint |
382 | */ | 353 | */ |
354 | static int bfin_twi_master_xfer(struct i2c_adapter *adap, | ||
355 | struct i2c_msg *msgs, int num) | ||
356 | { | ||
357 | return bfin_twi_do_master_xfer(adap, msgs, num); | ||
358 | } | ||
383 | 359 | ||
384 | int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | 360 | /* |
361 | * One I2C SMBus transfer | ||
362 | */ | ||
363 | int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
385 | unsigned short flags, char read_write, | 364 | unsigned short flags, char read_write, |
386 | u8 command, int size, union i2c_smbus_data *data) | 365 | u8 command, int size, union i2c_smbus_data *data) |
387 | { | 366 | { |
@@ -469,7 +448,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
469 | iface->manual_stop = 0; | 448 | iface->manual_stop = 0; |
470 | iface->read_write = read_write; | 449 | iface->read_write = read_write; |
471 | iface->command = command; | 450 | iface->command = command; |
472 | iface->timeout_count = 10; | ||
473 | init_completion(&(iface->complete)); | 451 | init_completion(&(iface->complete)); |
474 | 452 | ||
475 | /* FIFO Initiation. Data in FIFO should be discarded before | 453 | /* FIFO Initiation. Data in FIFO should be discarded before |
@@ -486,9 +464,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
486 | write_MASTER_ADDR(iface, addr); | 464 | write_MASTER_ADDR(iface, addr); |
487 | SSYNC(); | 465 | SSYNC(); |
488 | 466 | ||
489 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
490 | add_timer(&iface->timeout_timer); | ||
491 | |||
492 | switch (iface->cur_mode) { | 467 | switch (iface->cur_mode) { |
493 | case TWI_I2C_MODE_STANDARDSUB: | 468 | case TWI_I2C_MODE_STANDARDSUB: |
494 | write_XMT_DATA8(iface, iface->command); | 469 | write_XMT_DATA8(iface, iface->command); |
@@ -550,10 +525,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
550 | else if (iface->readNum > 255) { | 525 | else if (iface->readNum > 255) { |
551 | write_MASTER_CTL(iface, 0xff << 6); | 526 | write_MASTER_CTL(iface, 0xff << 6); |
552 | iface->manual_stop = 1; | 527 | iface->manual_stop = 1; |
553 | } else { | 528 | } else |
554 | del_timer(&iface->timeout_timer); | ||
555 | break; | 529 | break; |
556 | } | ||
557 | } | 530 | } |
558 | } | 531 | } |
559 | write_INT_MASK(iface, MCOMP | MERR | | 532 | write_INT_MASK(iface, MCOMP | MERR | |
@@ -569,7 +542,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
569 | } | 542 | } |
570 | SSYNC(); | 543 | SSYNC(); |
571 | 544 | ||
572 | wait_for_completion(&iface->complete); | 545 | while (!iface->result) { |
546 | if (!wait_for_completion_timeout(&iface->complete, | ||
547 | adap->timeout)) { | ||
548 | iface->result = -1; | ||
549 | dev_err(&adap->dev, "smbus transfer timeout\n"); | ||
550 | } | ||
551 | } | ||
573 | 552 | ||
574 | rc = (iface->result >= 0) ? 0 : -1; | 553 | rc = (iface->result >= 0) ? 0 : -1; |
575 | 554 | ||
@@ -577,6 +556,17 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
577 | } | 556 | } |
578 | 557 | ||
579 | /* | 558 | /* |
559 | * Generic I2C SMBus transfer entrypoint | ||
560 | */ | ||
561 | int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
562 | unsigned short flags, char read_write, | ||
563 | u8 command, int size, union i2c_smbus_data *data) | ||
564 | { | ||
565 | return bfin_twi_do_smbus_xfer(adap, addr, flags, | ||
566 | read_write, command, size, data); | ||
567 | } | ||
568 | |||
569 | /* | ||
580 | * Return what the adapter supports | 570 | * Return what the adapter supports |
581 | */ | 571 | */ |
582 | static u32 bfin_twi_functionality(struct i2c_adapter *adap) | 572 | static u32 bfin_twi_functionality(struct i2c_adapter *adap) |
@@ -667,10 +657,6 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) | |||
667 | goto out_error_no_irq; | 657 | goto out_error_no_irq; |
668 | } | 658 | } |
669 | 659 | ||
670 | init_timer(&(iface->timeout_timer)); | ||
671 | iface->timeout_timer.function = bfin_twi_timeout; | ||
672 | iface->timeout_timer.data = (unsigned long)iface; | ||
673 | |||
674 | p_adap = &iface->adap; | 660 | p_adap = &iface->adap; |
675 | p_adap->nr = pdev->id; | 661 | p_adap->nr = pdev->id; |
676 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); | 662 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); |
@@ -678,6 +664,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) | |||
678 | p_adap->algo_data = iface; | 664 | p_adap->algo_data = iface; |
679 | p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | 665 | p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; |
680 | p_adap->dev.parent = &pdev->dev; | 666 | p_adap->dev.parent = &pdev->dev; |
667 | p_adap->timeout = 5 * HZ; | ||
668 | p_adap->retries = 3; | ||
681 | 669 | ||
682 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); | 670 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); |
683 | if (rc) { | 671 | if (rc) { |