RE: [PATCH V4 3/7] i2c: qup: Add V2 tags support

2015-07-21 Thread Sricharan
Hi Ivan,

 -Original Message-
 From: Ivan T. Ivanov [mailto:iiva...@mm-sol.com]
 Sent: Monday, July 20, 2015 3:14 PM
 To: Sricharan R
 Cc: devicet...@vger.kernel.org; linux-arm-...@vger.kernel.org;
 ga...@codeaurora.org; linux-ker...@vger.kernel.org; linux-
 i...@vger.kernel.org; agr...@codeaurora.org; dmaeng...@vger.kernel.org;
 linux-arm-ker...@lists.infradead.org
 Subject: Re: [PATCH V4 3/7] i2c: qup: Add V2 tags support
 
 
 Hi Sricharan,
 
 On Thu, 2015-07-09 at 08:55 +0530, Sricharan R wrote:
  QUP from version 2.1.1 onwards, supports a new format of i2c command
  tags. Tag codes instructs the controller to perform a operation like
  read/write. This new tagging version supports bam dma and transfers of
  more than 256 bytes without 'stop'
  in between. Adding the support for the same.
 
 IIRC, more than 256 bytes in message is supported only in BAM(DMA) mode,
 if this is true, please be more explicit in commit message.

   More than 256 byte read transfers are possible in V2 mode and not possible 
only
   in V1 mode.  So qup_i2c_quirks should be populated only for V1 mode and V2 
mode
   during probe.

 
 You haven't tried to read more than 256 bytes with this patch, right? See
 qup_i2c_quirks ;-)
 Ya I have tested for 256 bytes transfer in my previous series, not on
 this one. My bad. Should have error'ed out with qup_i2c_quirks in place.
 Anyways will not populate qup_i2c_quirks for v2 mode.

 
 
 
   struct qup_i2c_dev {
  struct device*dev;
  void __iomem*base;
  @@ -117,6 +138,7 @@ struct qup_i2c_dev {
  int in_blk_sz;
 
  unsigned longone_byte_t;
  +   struct qup_i2c_blockblk;
 
  struct i2c_msg*msg;
  /* Current posion in user message buffer */ @@ -126,6 +148,14
  @@ struct qup_i2c_dev {
  /* QUP core errors */
  u32 qup_err;
 
  +   int use_v2_tags;
  +
  +   int (*qup_i2c_write_one)(struct qup_i2c_dev *qup,
  +   struct i2c_msg *msg);
  +
  +   int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
  +   struct i2c_msg *msg);
  +
 
 Do we really need additional level of indirection?
 
 We have separate struct i2c_algorithm, then we have common
 qup_i2c_read/write methods and then we have different read/write sub
 functions. I don't think 3-4 lines code reuse deserve increased complexity.

   Infact I was thinking this way as well. But anyways wanted to get reviewed
   and see which was better. Will change this.

 
 snip
 
  +static void qup_i2c_get_blk_data(struct qup_i2c_dev *qup,
  +   struct i2c_msg *msg) {
 
 This is more like set_blk_metadata. Second argument could fit line above.
 
 Ok. Will change name and indentation.

  +   memset(qup-blk, 0, sizeof(qup-blk));
  +
  +   if (!qup-use_v2_tags) {
  +   if (!(msg-flags  I2C_M_RD))
  +   qup-blk.tx_tag_len = 1;
  +   return;
  +   }
  +
  +   qup-blk.data_len = msg-len;
  +   qup-blk.count = (msg-len + QUP_READ_LIMIT - 1) /
  + QUP_READ_LIMIT;
  +
  +   /* 4 bytes for first block and 2 writes for rest */
  +   qup-blk.tx_tag_len = 4 + (qup-blk.count - 1) * 2;
  +
  +   /* There are 2 tag bytes that are read in to fifo for every block */
  +   if (msg-flags  I2C_M_RD)
  +   qup-blk.rx_tag_len = qup-blk.count * 2; }
  +
 
 snip
 
  +static int qup_i2c_get_tags(u8 *tags, struct qup_i2c_dev *qup,
  +   struct i2c_msg
  +*msg) {
 
 This is more like set_tags.

 Ok, will change.
 
  +   u16 addr = (msg-addr  1) | ((msg-flags  I2C_M_RD) ==
 I2C_M_RD);
  +   int len = 0;
  +   int data_len;
  +
  +   if (qup-blk.pos == 0) {
  +   tags[len++] = QUP_TAG_V2_START;
  +   tags[len++] = addr  0xff;
  +
  +   if (msg-flags  I2C_M_TEN)
  +   tags[len++] = addr  8;
  +   }
  +
  +   /* Send _STOP commands for the last block */
  +   if (qup-blk.pos == (qup-blk.count - 1)) {
  +   if (msg-flags  I2C_M_RD)
  +   tags[len++] = QUP_TAG_V2_DATARD_STOP;
  +   else
  +   tags[len++] = QUP_TAG_V2_DATAWR_STOP;
  +   } else {
  +   if (msg-flags  I2C_M_RD)
  +   tags[len++] = QUP_TAG_V2_DATARD;
  +   else
  +   tags[len++] = QUP_TAG_V2_DATAWR;
  +   }
  +
  +   data_len = qup_i2c_get_data_len(qup);
  +
  +   /* 0 implies 256 bytes */
  +   if (data_len == QUP_READ_LIMIT)
  +   tags[len++] = 0;
  +   else
  +   tags[len++] = data_len;
  +
  +   return len;
  +}
  +

Regards,
  Sricharan

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org

Re: [PATCH V4 3/7] i2c: qup: Add V2 tags support

2015-07-20 Thread Ivan T. Ivanov

Hi Sricharan,

On Thu, 2015-07-09 at 08:55 +0530, Sricharan R wrote:
 QUP from version 2.1.1 onwards, supports a new format of
 i2c command tags. Tag codes instructs the controller to
 perform a operation like read/write. This new tagging version
 supports bam dma and transfers of more than 256 bytes without 'stop'
 in between. Adding the support for the same.

IIRC, more than 256 bytes in message is supported only in BAM(DMA)
mode, if this is true, please be more explicit in commit message.

You haven't tried to read more than 256 bytes with this
patch, right? See qup_i2c_quirks ;-) 

 
 
  struct qup_i2c_dev {
 struct device*dev;
 void __iomem*base;
 @@ -117,6 +138,7 @@ struct qup_i2c_dev {
 int in_blk_sz;
 
 unsigned longone_byte_t;
 +   struct qup_i2c_blockblk;
 
 struct i2c_msg*msg;
 /* Current posion in user message buffer */
 @@ -126,6 +148,14 @@ struct qup_i2c_dev {
 /* QUP core errors */
 u32 qup_err;
 
 +   int use_v2_tags;
 +
 +   int (*qup_i2c_write_one)(struct qup_i2c_dev *qup,
 +   struct i2c_msg *msg);
 +
 +   int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
 +   struct i2c_msg *msg);
 +

Do we really need additional level of indirection?

We have separate struct i2c_algorithm, then we have common 
qup_i2c_read/write methods and then we have different 
read/write sub functions. I don't think 3-4 lines code reuse
deserve increased complexity.

snip

 +static void qup_i2c_get_blk_data(struct qup_i2c_dev *qup,
 +   struct i2c_msg *msg)
 +{

This is more like set_blk_metadata. Second argument could fit line above.

 +   memset(qup-blk, 0, sizeof(qup-blk));
 +
 +   if (!qup-use_v2_tags) {
 +   if (!(msg-flags  I2C_M_RD))
 +   qup-blk.tx_tag_len = 1;
 +   return;
 +   }
 +
 +   qup-blk.data_len = msg-len;
 +   qup-blk.count = (msg-len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
 +
 +   /* 4 bytes for first block and 2 writes for rest */
 +   qup-blk.tx_tag_len = 4 + (qup-blk.count - 1) * 2;
 +
 +   /* There are 2 tag bytes that are read in to fifo for every block */
 +   if (msg-flags  I2C_M_RD)
 +   qup-blk.rx_tag_len = qup-blk.count * 2;
 +}
 +

snip

 +static int qup_i2c_get_tags(u8 *tags, struct qup_i2c_dev *qup,
 +   struct i2c_msg *msg)
 +{

This is more like set_tags.

 +   u16 addr = (msg-addr  1) | ((msg-flags  I2C_M_RD) == I2C_M_RD);
 +   int len = 0;
 +   int data_len;
 +
 +   if (qup-blk.pos == 0) {
 +   tags[len++] = QUP_TAG_V2_START;
 +   tags[len++] = addr  0xff;
 +
 +   if (msg-flags  I2C_M_TEN)
 +   tags[len++] = addr  8;
 +   }
 +
 +   /* Send _STOP commands for the last block */
 +   if (qup-blk.pos == (qup-blk.count - 1)) {
 +   if (msg-flags  I2C_M_RD)
 +   tags[len++] = QUP_TAG_V2_DATARD_STOP;
 +   else
 +   tags[len++] = QUP_TAG_V2_DATAWR_STOP;
 +   } else {
 +   if (msg-flags  I2C_M_RD)
 +   tags[len++] = QUP_TAG_V2_DATARD;
 +   else
 +   tags[len++] = QUP_TAG_V2_DATAWR;
 +   }
 +
 +   data_len = qup_i2c_get_data_len(qup);
 +
 +   /* 0 implies 256 bytes */
 +   if (data_len == QUP_READ_LIMIT)
 +   tags[len++] = 0;
 +   else
 +   tags[len++] = data_len;
 +
 +   return len;
 +}
 +

Regards,
Ivan

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 3/7] i2c: qup: Add V2 tags support

2015-07-08 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of
i2c command tags. Tag codes instructs the controller to
perform a operation like read/write. This new tagging version
supports bam dma and transfers of more than 256 bytes without 'stop'
in between. Adding the support for the same.

For each block a data_write/read tag and data_len tag is added to
the output fifo. For the final block of data write_stop/read_stop
tag is used.

Signed-off-by: Andy Gross agr...@codeaurora.org
Signed-off-by: Sricharan R sricha...@codeaurora.org
---
 drivers/i2c/busses/i2c-qup.c | 330 ++-
 1 file changed, 323 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 131dc28..a4e20d9 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -43,6 +43,8 @@
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
 
+#define QUP_I2C_MASTER_GEN 0x408
+
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
 #define QUP_RUN_STATE  1
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATEBIT(13)
 #define I2C_MINI_CORE  (2  8)
 #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
 /* Most significant word offset in FIFO port */
 #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)
 
@@ -79,6 +83,7 @@
 #define QUP_PACK_ENBIT(15)
 
 #define QUP_REPACK_EN  (QUP_UNPACK_EN | QUP_PACK_EN)
+#define QUP_V2_TAGS_EN 1
 
 #define QUP_OUTPUT_BLOCK_SIZE(x)(((x)  0)  0x03)
 #define QUP_OUTPUT_FIFO_SIZE(x)(((x)  2)  0x07)
@@ -91,6 +96,13 @@
 #define QUP_TAG_STOP   (3  8)
 #define QUP_TAG_REC(4  8)
 
+/* QUP v2 tags */
+#define QUP_TAG_V2_START   0x81
+#define QUP_TAG_V2_DATAWR  0x82
+#define QUP_TAG_V2_DATAWR_STOP 0x83
+#define QUP_TAG_V2_DATARD  0x85
+#define QUP_TAG_V2_DATARD_STOP 0x87
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL  BIT(0)
 #define I2C_STATUS_BUS_ACTIVE  BIT(8)
@@ -102,6 +114,15 @@
 #define RESET_BIT  0x0
 #define ONE_BYTE   0x1
 
+struct qup_i2c_block {
+   int count;
+   int pos;
+   int tx_tag_len;
+   int rx_tag_len;
+   int data_len;
+   u8  tags[6];
+};
+
 struct qup_i2c_dev {
struct device   *dev;
void __iomem*base;
@@ -117,6 +138,7 @@ struct qup_i2c_dev {
int in_blk_sz;
 
unsigned long   one_byte_t;
+   struct qup_i2c_blockblk;
 
struct i2c_msg  *msg;
/* Current posion in user message buffer */
@@ -126,6 +148,14 @@ struct qup_i2c_dev {
/* QUP core errors */
u32 qup_err;
 
+   int use_v2_tags;
+
+   int (*qup_i2c_write_one)(struct qup_i2c_dev *qup,
+struct i2c_msg *msg);
+
+   int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
+   struct i2c_msg *msg);
+
struct completion   xfer;
 };
 
@@ -266,7 +296,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
 static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
*msg)
 {
/* Number of entries to shift out, including the start */
-   int total = msg-len + 1;
+   int total = msg-len + qup-blk.tx_tag_len;
 
if (total  qup-out_fifo_sz) {
/* FIFO mode */
@@ -324,6 +354,134 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
return ret;
 }
 
+static void qup_i2c_get_blk_data(struct qup_i2c_dev *qup,
+struct i2c_msg *msg)
+{
+   memset(qup-blk, 0, sizeof(qup-blk));
+
+   if (!qup-use_v2_tags) {
+   if (!(msg-flags  I2C_M_RD))
+   qup-blk.tx_tag_len = 1;
+   return;
+   }
+
+   qup-blk.data_len = msg-len;
+   qup-blk.count = (msg-len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
+
+   /* 4 bytes for first block and 2 writes for rest */
+   qup-blk.tx_tag_len = 4 + (qup-blk.count - 1) * 2;
+
+   /* There are 2 tag bytes that are read in to fifo for every block */
+   if (msg-flags  I2C_M_RD)
+   qup-blk.rx_tag_len = qup-blk.count * 2;
+}
+
+static int qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
+int dlen, u8 *dbuf)
+{
+   u32 val = 0, idx = 0, pos = 0, i = 0, t;
+   int  len = tlen + dlen;
+   u8 *buf = tbuf;
+   int ret = 0;
+
+   while (len  0) {
+   ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL,
+RESET_BIT, 4 * ONE_BYTE);
+   if (ret) {
+   dev_err(qup-dev, timeout for fifo out full);
+   return ret;
+   }
+
+