aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTang Yuantian <B29983@freescale.com>2012-02-23 04:42:45 -0500
committerWolfram Sang <w.sang@pengutronix.de>2012-02-24 16:25:30 -0500
commit3f0e1e4bb6a73dce9aed9f82a86f4ae161bf9b06 (patch)
treea2f41a012d830ef732feb16be462697beda0c77b /drivers
parent237ab4062d084a3350ff2516d1b39401b2cb87c6 (diff)
i2c: mpc: Add support for SMBUS_READ_BLOCK_DATA
Add support for SMBUS_READ_BLOCK_DATA to the i2c-mpc bus driver. Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com> Cc: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-mpc.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a8ebb84e23f9..206caacd30d7 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -454,7 +454,7 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
454} 454}
455 455
456static int mpc_read(struct mpc_i2c *i2c, int target, 456static int mpc_read(struct mpc_i2c *i2c, int target,
457 u8 *data, int length, int restart) 457 u8 *data, int length, int restart, bool recv_len)
458{ 458{
459 unsigned timeout = i2c->adap.timeout; 459 unsigned timeout = i2c->adap.timeout;
460 int i, result; 460 int i, result;
@@ -470,7 +470,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
470 return result; 470 return result;
471 471
472 if (length) { 472 if (length) {
473 if (length == 1) 473 if (length == 1 && !recv_len)
474 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); 474 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
475 else 475 else
476 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA); 476 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
@@ -479,17 +479,46 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
479 } 479 }
480 480
481 for (i = 0; i < length; i++) { 481 for (i = 0; i < length; i++) {
482 u8 byte;
483
482 result = i2c_wait(i2c, timeout, 0); 484 result = i2c_wait(i2c, timeout, 0);
483 if (result < 0) 485 if (result < 0)
484 return result; 486 return result;
485 487
486 /* Generate txack on next to last byte */ 488 /*
487 if (i == length - 2) 489 * For block reads, we have to know the total length (1st byte)
488 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); 490 * before we can determine if we are done.
489 /* Do not generate stop on last byte */ 491 */
490 if (i == length - 1) 492 if (i || !recv_len) {
491 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX); 493 /* Generate txack on next to last byte */
492 data[i] = readb(i2c->base + MPC_I2C_DR); 494 if (i == length - 2)
495 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
496 | CCR_TXAK);
497 /* Do not generate stop on last byte */
498 if (i == length - 1)
499 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
500 | CCR_MTX);
501 }
502
503 byte = readb(i2c->base + MPC_I2C_DR);
504
505 /*
506 * Adjust length if first received byte is length.
507 * The length is 1 length byte plus actually data length
508 */
509 if (i == 0 && recv_len) {
510 if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX)
511 return -EPROTO;
512 length += byte;
513 /*
514 * For block reads, generate txack here if data length
515 * is 1 byte (total length is 2 bytes).
516 */
517 if (length == 2)
518 writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
519 | CCR_TXAK);
520 }
521 data[i] = byte;
493 } 522 }
494 523
495 return length; 524 return length;
@@ -532,12 +561,17 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
532 "Doing %s %d bytes to 0x%02x - %d of %d messages\n", 561 "Doing %s %d bytes to 0x%02x - %d of %d messages\n",
533 pmsg->flags & I2C_M_RD ? "read" : "write", 562 pmsg->flags & I2C_M_RD ? "read" : "write",
534 pmsg->len, pmsg->addr, i + 1, num); 563 pmsg->len, pmsg->addr, i + 1, num);
535 if (pmsg->flags & I2C_M_RD) 564 if (pmsg->flags & I2C_M_RD) {
536 ret = 565 bool recv_len = pmsg->flags & I2C_M_RECV_LEN;
537 mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); 566
538 else 567 ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i,
568 recv_len);
569 if (recv_len && ret > 0)
570 pmsg->len = ret;
571 } else {
539 ret = 572 ret =
540 mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); 573 mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
574 }
541 } 575 }
542 mpc_i2c_stop(i2c); 576 mpc_i2c_stop(i2c);
543 return (ret < 0) ? ret : num; 577 return (ret < 0) ? ret : num;
@@ -545,7 +579,8 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
545 579
546static u32 mpc_functionality(struct i2c_adapter *adap) 580static u32 mpc_functionality(struct i2c_adapter *adap)
547{ 581{
548 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 582 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
583 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
549} 584}
550 585
551static const struct i2c_algorithm mpc_algo = { 586static const struct i2c_algorithm mpc_algo = {