All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/6]  i2c: qup: Add support for v2 tags and bam dma
@ 2015-04-11  7:08 ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:08 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: sricharan-sgV2jX0FEOL9JmXXK+q4OQ

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 and is required for adding bam dma
capabilities. v2 tags supports transfer of more than 256 bytes in a single
i2c transaction. Also adding bam dma support facilitates transferring each
i2c_msg in i2c_msgs without a 'stop' bit in between which is required for
some of the clients.

This series depends on the below bam dma bug fix
 https://lkml.org/lkml/2015/2/20/47

Tested this series on apq8074 dragon board eeprom client on i2c bus1

[V3] Added support to coalesce each i2c_msg in i2c_msgs for fifo and
     block mode in Patch 2. Also addressed further code comments.

[V2] Addressed comments from Ivan T. Ivanov, Andy Gross [v1] Initial Version

Andy Gross (1):
  i2c: qup: Add V2 tags support

Sricharan R (5):
  i2c: qup: Change qup_wait_writeready function to use for all timeouts
  i2c: qup: Add bam dma capabilities
  i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
  dts: msm8974: Add blsp2_bam dma node
  dts: msm8974: Add dma channels for blsp2_i2c1 node

 arch/arm/boot/dts/qcom-msm8974.dtsi |  14 +-
 drivers/i2c/busses/i2c-qup.c        | 877 +++++++++++++++++++++++++++++++++---
 2 files changed, 822 insertions(+), 69 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 0/6]  i2c: qup: Add support for v2 tags and bam dma
@ 2015-04-11  7:08 ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:08 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

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 and is required for adding bam dma
capabilities. v2 tags supports transfer of more than 256 bytes in a single
i2c transaction. Also adding bam dma support facilitates transferring each
i2c_msg in i2c_msgs without a 'stop' bit in between which is required for
some of the clients.

This series depends on the below bam dma bug fix
 https://lkml.org/lkml/2015/2/20/47

Tested this series on apq8074 dragon board eeprom client on i2c bus1

[V3] Added support to coalesce each i2c_msg in i2c_msgs for fifo and
     block mode in Patch 2. Also addressed further code comments.

[V2] Addressed comments from Ivan T. Ivanov, Andy Gross [v1] Initial Version

Andy Gross (1):
  i2c: qup: Add V2 tags support

Sricharan R (5):
  i2c: qup: Change qup_wait_writeready function to use for all timeouts
  i2c: qup: Add bam dma capabilities
  i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
  dts: msm8974: Add blsp2_bam dma node
  dts: msm8974: Add dma channels for blsp2_i2c1 node

 arch/arm/boot/dts/qcom-msm8974.dtsi |  14 +-
 drivers/i2c/busses/i2c-qup.c        | 877 +++++++++++++++++++++++++++++++++---
 2 files changed, 822 insertions(+), 69 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 0/6]  i2c: qup: Add support for v2 tags and bam dma
@ 2015-04-11  7:08 ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

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 and is required for adding bam dma
capabilities. v2 tags supports transfer of more than 256 bytes in a single
i2c transaction. Also adding bam dma support facilitates transferring each
i2c_msg in i2c_msgs without a 'stop' bit in between which is required for
some of the clients.

This series depends on the below bam dma bug fix
 https://lkml.org/lkml/2015/2/20/47

Tested this series on apq8074 dragon board eeprom client on i2c bus1

[V3] Added support to coalesce each i2c_msg in i2c_msgs for fifo and
     block mode in Patch 2. Also addressed further code comments.

[V2] Addressed comments from Ivan T. Ivanov, Andy Gross [v1] Initial Version

Andy Gross (1):
  i2c: qup: Add V2 tags support

Sricharan R (5):
  i2c: qup: Change qup_wait_writeready function to use for all timeouts
  i2c: qup: Add bam dma capabilities
  i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
  dts: msm8974: Add blsp2_bam dma node
  dts: msm8974: Add dma channels for blsp2_i2c1 node

 arch/arm/boot/dts/qcom-msm8974.dtsi |  14 +-
 drivers/i2c/busses/i2c-qup.c        | 877 +++++++++++++++++++++++++++++++++---
 2 files changed, 822 insertions(+), 69 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts
  2015-04-11  7:08 ` Sricharan R
  (?)
@ 2015-04-11  7:09     ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: sricharan-sgV2jX0FEOL9JmXXK+q4OQ

qup_wait_writeready waits only on a output fifo empty event.
Change the same function to accept the event and data length
to wait as parameters. This way the same function can be used for
timeouts in otherplaces as well.

Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
[v3] Addressed comments from Andy Gross <agross-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

 drivers/i2c/busses/i2c-qup.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4dad23b..9ccf3e8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -98,6 +98,9 @@
 #define QUP_STATUS_ERROR_FLAGS		0x7c
 
 #define QUP_READ_LIMIT			256
+#define SET_BIT				0x1
+#define RESET_BIT			0x0
+#define ONE_BYTE			0x1
 
 struct qup_i2c_dev {
 	struct device		*dev;
@@ -221,26 +224,42 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
 	return 0;
 }
 
-static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup)
+/**
+ * qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path
+ * @qup: The qup_i2c_dev device
+ * @op: The bit/event to wait on
+ * @val: value of the bit to wait on, 0 or 1
+ * @len: The length the bytes to be transferred
+ */
+static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
+			      int len)
 {
 	unsigned long timeout;
 	u32 opflags;
 	u32 status;
+	u32 shift = __ffs(op);
 
-	timeout = jiffies + HZ;
+	len *= qup->one_byte_t;
+	/* timeout after a wait of twice the max time */
+	timeout = jiffies + len * 4;
 
 	for (;;) {
 		opflags = readl(qup->base + QUP_OPERATIONAL);
 		status = readl(qup->base + QUP_I2C_STATUS);
 
-		if (!(opflags & QUP_OUT_NOT_EMPTY) &&
-		    !(status & I2C_STATUS_BUS_ACTIVE))
-			return 0;
+		if (((opflags & op) >> shift) == val) {
+			if (op == QUP_OUT_NOT_EMPTY) {
+				if (!(status & I2C_STATUS_BUS_ACTIVE))
+					return 0;
+			} else {
+				return 0;
+			}
+		}
 
 		if (time_after(jiffies, timeout))
 			return -ETIMEDOUT;
 
-		usleep_range(qup->one_byte_t, qup->one_byte_t * 2);
+		usleep_range(len, len * 2);
 	}
 }
 
@@ -347,7 +366,7 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	} while (qup->pos < msg->len);
 
 	/* Wait for the outstanding data in the fifo to drain */
-	ret = qup_i2c_wait_writeready(qup);
+	ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
 
 err:
 	disable_irq(qup->irq);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

qup_wait_writeready waits only on a output fifo empty event.
Change the same function to accept the event and data length
to wait as parameters. This way the same function can be used for
timeouts in otherplaces as well.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[v3] Addressed comments from Andy Gross <agross@codeaurora.org>

 drivers/i2c/busses/i2c-qup.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4dad23b..9ccf3e8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -98,6 +98,9 @@
 #define QUP_STATUS_ERROR_FLAGS		0x7c
 
 #define QUP_READ_LIMIT			256
+#define SET_BIT				0x1
+#define RESET_BIT			0x0
+#define ONE_BYTE			0x1
 
 struct qup_i2c_dev {
 	struct device		*dev;
@@ -221,26 +224,42 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
 	return 0;
 }
 
-static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup)
+/**
+ * qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path
+ * @qup: The qup_i2c_dev device
+ * @op: The bit/event to wait on
+ * @val: value of the bit to wait on, 0 or 1
+ * @len: The length the bytes to be transferred
+ */
+static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
+			      int len)
 {
 	unsigned long timeout;
 	u32 opflags;
 	u32 status;
+	u32 shift = __ffs(op);
 
-	timeout = jiffies + HZ;
+	len *= qup->one_byte_t;
+	/* timeout after a wait of twice the max time */
+	timeout = jiffies + len * 4;
 
 	for (;;) {
 		opflags = readl(qup->base + QUP_OPERATIONAL);
 		status = readl(qup->base + QUP_I2C_STATUS);
 
-		if (!(opflags & QUP_OUT_NOT_EMPTY) &&
-		    !(status & I2C_STATUS_BUS_ACTIVE))
-			return 0;
+		if (((opflags & op) >> shift) == val) {
+			if (op == QUP_OUT_NOT_EMPTY) {
+				if (!(status & I2C_STATUS_BUS_ACTIVE))
+					return 0;
+			} else {
+				return 0;
+			}
+		}
 
 		if (time_after(jiffies, timeout))
 			return -ETIMEDOUT;
 
-		usleep_range(qup->one_byte_t, qup->one_byte_t * 2);
+		usleep_range(len, len * 2);
 	}
 }
 
@@ -347,7 +366,7 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	} while (qup->pos < msg->len);
 
 	/* Wait for the outstanding data in the fifo to drain */
-	ret = qup_i2c_wait_writeready(qup);
+	ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
 
 err:
 	disable_irq(qup->irq);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

qup_wait_writeready waits only on a output fifo empty event.
Change the same function to accept the event and data length
to wait as parameters. This way the same function can be used for
timeouts in otherplaces as well.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[v3] Addressed comments from Andy Gross <agross@codeaurora.org>

 drivers/i2c/busses/i2c-qup.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4dad23b..9ccf3e8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -98,6 +98,9 @@
 #define QUP_STATUS_ERROR_FLAGS		0x7c
 
 #define QUP_READ_LIMIT			256
+#define SET_BIT				0x1
+#define RESET_BIT			0x0
+#define ONE_BYTE			0x1
 
 struct qup_i2c_dev {
 	struct device		*dev;
@@ -221,26 +224,42 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
 	return 0;
 }
 
-static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup)
+/**
+ * qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path
+ * @qup: The qup_i2c_dev device
+ * @op: The bit/event to wait on
+ * @val: value of the bit to wait on, 0 or 1
+ * @len: The length the bytes to be transferred
+ */
+static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
+			      int len)
 {
 	unsigned long timeout;
 	u32 opflags;
 	u32 status;
+	u32 shift = __ffs(op);
 
-	timeout = jiffies + HZ;
+	len *= qup->one_byte_t;
+	/* timeout after a wait of twice the max time */
+	timeout = jiffies + len * 4;
 
 	for (;;) {
 		opflags = readl(qup->base + QUP_OPERATIONAL);
 		status = readl(qup->base + QUP_I2C_STATUS);
 
-		if (!(opflags & QUP_OUT_NOT_EMPTY) &&
-		    !(status & I2C_STATUS_BUS_ACTIVE))
-			return 0;
+		if (((opflags & op) >> shift) == val) {
+			if (op == QUP_OUT_NOT_EMPTY) {
+				if (!(status & I2C_STATUS_BUS_ACTIVE))
+					return 0;
+			} else {
+				return 0;
+			}
+		}
 
 		if (time_after(jiffies, timeout))
 			return -ETIMEDOUT;
 
-		usleep_range(qup->one_byte_t, qup->one_byte_t * 2);
+		usleep_range(len, len * 2);
 	}
 }
 
@@ -347,7 +366,7 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	} while (qup->pos < msg->len);
 
 	/* Wait for the outstanding data in the fifo to drain */
-	ret = qup_i2c_wait_writeready(qup);
+	ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
 
 err:
 	disable_irq(qup->irq);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-11  7:08 ` Sricharan R
@ 2015-04-11  7:09   ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

From: Andy Gross <agross@codeaurora.org>

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 <agross@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[V3] Addressed comments from Andy Gross <agross@codeaurora.org>
     to coalesce each i2c_msg in i2c_msgs as a single transfer.
     Added macros to i2c_wait_ready function.

 drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 337 insertions(+), 56 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 9ccf3e8..16a8f69 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -42,6 +43,7 @@
 #define QUP_IN_FIFO_BASE	0x218
 #define QUP_I2C_CLK_CTL		0x400
 #define QUP_I2C_STATUS		0x404
+#define QUP_I2C_MASTER_GEN	0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE		0
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATE	BIT(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)
 
@@ -80,17 +84,30 @@
 
 #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)
 #define QUP_INPUT_BLOCK_SIZE(x)	(((x) >> 5) & 0x03)
 #define QUP_INPUT_FIFO_SIZE(x)	(((x) >> 7) & 0x07)
 
-/* QUP tags */
+/* QUP V1 tags */
 #define QUP_TAG_START		(1 << 8)
 #define QUP_TAG_DATA		(2 << 8)
 #define QUP_TAG_STOP		(3 << 8)
 #define QUP_TAG_REC		(4 << 8)
 
+/* QUP v2 tags */
+#define QUP_TAG_V2_HS                  0xff
+#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
+
+/* frequency definitions for high speed and max speed */
+#define I2C_QUP_CLK_FAST_FREQ          1000000
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL	BIT(0)
 #define I2C_STATUS_BUS_ACTIVE		BIT(8)
@@ -102,6 +119,15 @@
 #define RESET_BIT			0x0
 #define ONE_BYTE			0x1
 
+#define QUP_I2C_MX_CONFIG_DURING_RUN	BIT(31)
+
+struct qup_i2c_block {
+	int	blocks;
+	u8	*block_tag_len;
+	int	*block_data_len;
+	int	block_pos;
+};
+
 struct qup_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
@@ -115,9 +141,17 @@ struct qup_i2c_dev {
 	int			in_fifo_sz;
 	int			out_blk_sz;
 	int			in_blk_sz;
-
+	struct	qup_i2c_block	blk;
 	unsigned long		one_byte_t;
 
+	int			is_hs;
+	bool			use_v2_tags;
+
+	int			tx_tag_len;
+	int			rx_tag_len;
+	u8			*tags;
+	int			tags_pos;
+
 	struct i2c_msg		*msg;
 	/* Current posion in user message buffer */
 	int			pos;
@@ -263,10 +297,19 @@ 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)
+static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+				   int run)
 {
-	/* Number of entries to shift out, including the start */
-	int total = msg->len + 1;
+	/* Total Number of entries to shift out, including the tags */
+	int total;
+
+	if (qup->use_v2_tags) {
+		total = msg->len + qup->tx_tag_len;
+		if (run)
+			total |= QUP_I2C_MX_CONFIG_DURING_RUN;
+	} else {
+		total = msg->len + 1; /* plus start tag */
+	}
 
 	if (total < qup->out_fifo_sz) {
 		/* FIFO mode */
@@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
 	u32 addr = msg->addr << 1;
 	u32 qup_tag;
@@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
+				  struct i2c_msg *msg, int last)
+{
+	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	int len = 0, prev_len = 0;
+	int blocks = 0;
+	int rem;
+	int block_len = 0;
+	int data_len;
+
+	qup->blk.block_pos = 0;
+	qup->pos = 0;
+	qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
+	rem = msg->len % QUP_READ_LIMIT;
+
+	/* 2 tag bytes for each block + 2 extra bytes for first block */
+	qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
+	qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
+	qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
+				  qup->blk.blocks, GFP_KERNEL);
+
+	while (blocks < qup->blk.blocks) {
+		/* 0 is used to specify a READ_LIMIT of 256 bytes */
+		data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
+
+		/* Send START and ADDR bytes only for the first block */
+		if (!blocks) {
+			qup->tags[len++] = QUP_TAG_V2_START;
+
+			if (qup->is_hs) {
+				qup->tags[len++] = QUP_TAG_V2_HS;
+				qup->tags[len++] = QUP_TAG_V2_START;
+			}
+
+			qup->tags[len++] = addr & 0xff;
+			if (msg->flags & I2C_M_TEN)
+				qup->tags[len++] = addr >> 8;
+		}
+
+		/* Send _STOP commands for the last block */
+		if ((blocks == (qup->blk.blocks - 1)) && last) {
+			if (msg->flags & I2C_M_RD)
+				qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
+			else
+				qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
+		} else {
+			if (msg->flags & I2C_M_RD)
+				qup->tags[len++] = QUP_TAG_V2_DATARD;
+			else
+				qup->tags[len++] = QUP_TAG_V2_DATAWR;
+		}
+
+		qup->tags[len++] = data_len;
+		block_len = len - prev_len;
+		prev_len = len;
+		qup->blk.block_tag_len[blocks] = block_len;
+
+		if (!data_len)
+			qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
+		else
+			qup->blk.block_data_len[blocks] = data_len;
+
+		qup->tags_pos = 0;
+		blocks++;
+	}
+
+	qup->tx_tag_len = len;
+
+	if (msg->flags & I2C_M_RD)
+		qup->rx_tag_len = (qup->blk.blocks * 2);
+	else
+		qup->rx_tag_len = 0;
+}
+
+static u32 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;
+
+	while (len > 0) {
+		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
+			dev_err(qup->dev, "timeout for fifo out full");
+			break;
+		}
+
+		t = (len >= 4) ? 4 : len;
+
+		while (idx < t) {
+			if (!i && (pos >= tlen)) {
+				buf = dbuf;
+				pos = 0;
+				i = 1;
+			}
+			val |= buf[pos++] << (idx++ * 8);
+		}
+
+		writel(val, qup->base + QUP_OUT_FIFO_BASE);
+		idx  = 0;
+		val = 0;
+		len -= 4;
+	}
+
+	return 0;
+}
+
+static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+	u32 data_len = 0, tag_len;
+
+	tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
+
+	if (!(msg->flags & I2C_M_RD))
+		data_len = qup->blk.block_data_len[qup->blk.block_pos];
+
+	qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
+}
+
+static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
+				*msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_issue_xfer_v2(qup, msg);
+	else
+		qup_i2c_issue_write_v1(qup, msg);
+}
+
+static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+			     int run, int last)
 {
 	unsigned long left;
 	int ret;
@@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	qup->msg = msg;
 	qup->pos = 0;
 
+	if (qup->use_v2_tags)
+		qup_i2c_create_tag_v2(qup, msg, last);
+	else
+		qup->blk.blocks = 0;
+
 	enable_irq(qup->irq);
 
-	qup_i2c_set_write_mode(qup, msg);
+	qup_i2c_set_write_mode(qup, msg, run);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+	if (!run) {
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
+	}
 
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
@@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 			ret = -EIO;
 			goto err;
 		}
-	} while (qup->pos < msg->len);
+		qup->blk.block_pos++;
+	} while (qup->blk.block_pos < qup->blk.blocks);
 
 	/* Wait for the outstanding data in the fifo to drain */
-	ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
+	if (last)
+		ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
+					 ONE_BYTE);
 
 err:
 	disable_irq(qup->irq);
@@ -375,8 +557,17 @@ err:
 	return ret;
 }
 
-static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
+static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
 {
+	if (qup->use_v2_tags) {
+		len += qup->rx_tag_len;
+		if (run) {
+			len |= QUP_I2C_MX_CONFIG_DURING_RUN;
+			qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
+		}
+		writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
+	}
+
 	if (len < qup->in_fifo_sz) {
 		/* FIFO mode */
 		writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
@@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
 	}
 }
 
-static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
+				  struct i2c_msg *msg)
 {
 	u32 addr, len, val;
 
@@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	writel(val, qup->base + QUP_OUT_FIFO_BASE);
 }
 
+static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
+			       *msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_issue_xfer_v2(qup, msg);
+	else
+		qup_i2c_issue_read_v1(qup, msg);
+}
 
-static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
-	u32 opflags;
 	u32 val = 0;
 	int idx;
+	int len = msg->len + qup->rx_tag_len;
 
-	for (idx = 0; qup->pos < msg->len; idx++) {
+	for (idx = 0; qup->pos < len; idx++) {
 		if ((idx & 1) == 0) {
 			/* Check that FIFO have data */
-			opflags = readl(qup->base + QUP_OPERATIONAL);
-			if (!(opflags & QUP_IN_NOT_EMPTY))
+			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+				dev_err(qup->dev, "timeout for fifo not empty");
 				break;
-
+			}
 			/* Reading 2 words at time */
 			val = readl(qup->base + QUP_IN_FIFO_BASE);
 
@@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
+				 struct i2c_msg *msg)
+{
+	u32 val;
+	int idx;
+	int pos = 0;
+	/* 2 extra bytes for read tags */
+	int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
+
+	while (pos < total) {
+		/* Check that FIFO have data */
+		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+			dev_err(qup->dev, "timeout for fifo not empty");
+			break;
+		}
+		val = readl(qup->base + QUP_IN_FIFO_BASE);
+
+		for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
+			/* first 2 bytes are tag bytes */
+			if (pos < 2)
+				continue;
+
+			if (pos >= total)
+				return;
+
+			msg->buf[qup->pos++] = val & 0xff;
+		}
+	}
+}
+
+static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
+			      struct i2c_msg *msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_read_fifo_v2(qup, msg);
+	else
+		qup_i2c_read_fifo_v1(qup, msg);
+}
+
+static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+			    int run, int last)
 {
 	unsigned long left;
 	int ret;
-
 	/*
 	 * The QUP block will issue a NACK and STOP on the bus when reaching
 	 * the end of the read, the length of the read is specified as one byte
@@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 
 	qup->msg = msg;
 	qup->pos  = 0;
+	if (qup->use_v2_tags)
+		qup_i2c_create_tag_v2(qup, msg, last);
+	else
+		qup->blk.blocks = 0;
 
 	enable_irq(qup->irq);
 
-	qup_i2c_set_read_mode(qup, msg->len);
+	qup_i2c_set_read_mode(qup, msg->len, run);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+	if (!run) {
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
+	}
 
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
-	ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
-	if (ret)
-		goto err;
+	do {
+		ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+		if (ret)
+			goto err;
 
-	qup_i2c_issue_read(qup, msg);
+		qup_i2c_issue_read(qup, msg);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
 
-	do {
 		left = wait_for_completion_timeout(&qup->xfer, HZ);
 		if (!left) {
 			writel(1, qup->base + QUP_SW_RESET);
@@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 		}
 
 		qup_i2c_read_fifo(qup, msg);
-	} while (qup->pos < msg->len);
+		qup->blk.block_pos++;
+	} while (qup->blk.block_pos < qup->blk.blocks);
 
 err:
 	disable_irq(qup->irq);
@@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx;
+	int ret, idx, last;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 		goto out;
 
 	/* Configure QUP as I2C mini core */
-	writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
+	if (qup->use_v2_tags) {
+		writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
+		writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
+	} else {
+		writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
+	}
 
 	for (idx = 0; idx < num; idx++) {
 		if (msgs[idx].len == 0) {
@@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			goto out;
 		}
 
+		reinit_completion(&qup->xfer);
+
+		last = (idx == (num - 1));
+
 		if (msgs[idx].flags & I2C_M_RD)
-			ret = qup_i2c_read_one(qup, &msgs[idx]);
+			ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
 		else
-			ret = qup_i2c_write_one(qup, &msgs[idx]);
+			ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
 
 		if (ret)
 			break;
+	}
 
+	if (!ret)
 		ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
-		if (ret)
-			break;
-	}
 
 	if (ret == 0)
 		ret = num;
 out:
 
+	if (qup->use_v2_tags) {
+		kfree(qup->tags);
+		kfree(qup->blk.block_tag_len);
+		kfree(qup->blk.block_data_len);
+	}
+
 	pm_runtime_mark_last_busy(qup->dev);
 	pm_runtime_put_autosuspend(qup->dev);
 
@@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
 	clk_prepare_enable(qup->pclk);
 }
 
+static const struct of_device_id qup_i2c_dt_match[] = {
+	{ .compatible = "qcom,i2c-qup-v1.1.1"},
+	{ .compatible = "qcom,i2c-qup-v2.1.1"},
+	{ .compatible = "qcom,i2c-qup-v2.2.1"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
+
 static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
 {
 	u32 config;
@@ -580,8 +848,9 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
+	int src_clk_freq, clk_freq_max;
 	u32 clk_freq = 100000;
+	const struct of_device_id *of_id;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 	if (!qup)
@@ -593,8 +862,19 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
 	of_property_read_u32(node, "clock-frequency", &clk_freq);
 
-	/* We support frequencies up to FAST Mode (400KHz) */
-	if (!clk_freq || clk_freq > 400000) {
+	of_id = of_match_node(qup_i2c_dt_match, node);
+
+	if (of_device_is_compatible(pdev->dev.of_node,
+				    "qcom,i2c-qup-v1.1.1")) {
+		qup->use_v2_tags = 0;
+		clk_freq_max = 400000;
+	} else {
+		qup->use_v2_tags = 1;
+		clk_freq_max = 3400000;
+	}
+
+	/* We support frequencies up to HIGH SPEED Mode (3400KHz) */
+	if (!clk_freq || clk_freq > clk_freq_max) {
 		dev_err(qup->dev, "clock frequency not supported %d\n",
 			clk_freq);
 		return -EINVAL;
@@ -672,8 +952,17 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
 	src_clk_freq = clk_get_rate(qup->clk);
-	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
-	hs_div = 3;
+	if (clk_freq > I2C_QUP_CLK_FAST_FREQ) {
+		fs_div = I2C_QUP_CLK_FAST_FREQ;
+		hs_div = (src_clk_freq / clk_freq) / 3;
+
+		qup->is_hs = 1;
+	} else {
+		fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+		hs_div = 3;
+	}
+
+	hs_div = min_t(int, hs_div, 0x7);
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
 
 	/*
@@ -770,14 +1059,6 @@ static const struct dev_pm_ops qup_i2c_qup_pm_ops = {
 		NULL)
 };
 
-static const struct of_device_id qup_i2c_dt_match[] = {
-	{ .compatible = "qcom,i2c-qup-v1.1.1" },
-	{ .compatible = "qcom,i2c-qup-v2.1.1" },
-	{ .compatible = "qcom,i2c-qup-v2.2.1" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
-
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-11  7:09   ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

From: Andy Gross <agross@codeaurora.org>

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 <agross@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[V3] Addressed comments from Andy Gross <agross@codeaurora.org>
     to coalesce each i2c_msg in i2c_msgs as a single transfer.
     Added macros to i2c_wait_ready function.

 drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 337 insertions(+), 56 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 9ccf3e8..16a8f69 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -42,6 +43,7 @@
 #define QUP_IN_FIFO_BASE	0x218
 #define QUP_I2C_CLK_CTL		0x400
 #define QUP_I2C_STATUS		0x404
+#define QUP_I2C_MASTER_GEN	0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE		0
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATE	BIT(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)
 
@@ -80,17 +84,30 @@
 
 #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)
 #define QUP_INPUT_BLOCK_SIZE(x)	(((x) >> 5) & 0x03)
 #define QUP_INPUT_FIFO_SIZE(x)	(((x) >> 7) & 0x07)
 
-/* QUP tags */
+/* QUP V1 tags */
 #define QUP_TAG_START		(1 << 8)
 #define QUP_TAG_DATA		(2 << 8)
 #define QUP_TAG_STOP		(3 << 8)
 #define QUP_TAG_REC		(4 << 8)
 
+/* QUP v2 tags */
+#define QUP_TAG_V2_HS                  0xff
+#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
+
+/* frequency definitions for high speed and max speed */
+#define I2C_QUP_CLK_FAST_FREQ          1000000
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL	BIT(0)
 #define I2C_STATUS_BUS_ACTIVE		BIT(8)
@@ -102,6 +119,15 @@
 #define RESET_BIT			0x0
 #define ONE_BYTE			0x1
 
+#define QUP_I2C_MX_CONFIG_DURING_RUN	BIT(31)
+
+struct qup_i2c_block {
+	int	blocks;
+	u8	*block_tag_len;
+	int	*block_data_len;
+	int	block_pos;
+};
+
 struct qup_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
@@ -115,9 +141,17 @@ struct qup_i2c_dev {
 	int			in_fifo_sz;
 	int			out_blk_sz;
 	int			in_blk_sz;
-
+	struct	qup_i2c_block	blk;
 	unsigned long		one_byte_t;
 
+	int			is_hs;
+	bool			use_v2_tags;
+
+	int			tx_tag_len;
+	int			rx_tag_len;
+	u8			*tags;
+	int			tags_pos;
+
 	struct i2c_msg		*msg;
 	/* Current posion in user message buffer */
 	int			pos;
@@ -263,10 +297,19 @@ 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)
+static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+				   int run)
 {
-	/* Number of entries to shift out, including the start */
-	int total = msg->len + 1;
+	/* Total Number of entries to shift out, including the tags */
+	int total;
+
+	if (qup->use_v2_tags) {
+		total = msg->len + qup->tx_tag_len;
+		if (run)
+			total |= QUP_I2C_MX_CONFIG_DURING_RUN;
+	} else {
+		total = msg->len + 1; /* plus start tag */
+	}
 
 	if (total < qup->out_fifo_sz) {
 		/* FIFO mode */
@@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
 	u32 addr = msg->addr << 1;
 	u32 qup_tag;
@@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
+				  struct i2c_msg *msg, int last)
+{
+	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	int len = 0, prev_len = 0;
+	int blocks = 0;
+	int rem;
+	int block_len = 0;
+	int data_len;
+
+	qup->blk.block_pos = 0;
+	qup->pos = 0;
+	qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
+	rem = msg->len % QUP_READ_LIMIT;
+
+	/* 2 tag bytes for each block + 2 extra bytes for first block */
+	qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
+	qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
+	qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
+				  qup->blk.blocks, GFP_KERNEL);
+
+	while (blocks < qup->blk.blocks) {
+		/* 0 is used to specify a READ_LIMIT of 256 bytes */
+		data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
+
+		/* Send START and ADDR bytes only for the first block */
+		if (!blocks) {
+			qup->tags[len++] = QUP_TAG_V2_START;
+
+			if (qup->is_hs) {
+				qup->tags[len++] = QUP_TAG_V2_HS;
+				qup->tags[len++] = QUP_TAG_V2_START;
+			}
+
+			qup->tags[len++] = addr & 0xff;
+			if (msg->flags & I2C_M_TEN)
+				qup->tags[len++] = addr >> 8;
+		}
+
+		/* Send _STOP commands for the last block */
+		if ((blocks == (qup->blk.blocks - 1)) && last) {
+			if (msg->flags & I2C_M_RD)
+				qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
+			else
+				qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
+		} else {
+			if (msg->flags & I2C_M_RD)
+				qup->tags[len++] = QUP_TAG_V2_DATARD;
+			else
+				qup->tags[len++] = QUP_TAG_V2_DATAWR;
+		}
+
+		qup->tags[len++] = data_len;
+		block_len = len - prev_len;
+		prev_len = len;
+		qup->blk.block_tag_len[blocks] = block_len;
+
+		if (!data_len)
+			qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
+		else
+			qup->blk.block_data_len[blocks] = data_len;
+
+		qup->tags_pos = 0;
+		blocks++;
+	}
+
+	qup->tx_tag_len = len;
+
+	if (msg->flags & I2C_M_RD)
+		qup->rx_tag_len = (qup->blk.blocks * 2);
+	else
+		qup->rx_tag_len = 0;
+}
+
+static u32 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;
+
+	while (len > 0) {
+		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
+			dev_err(qup->dev, "timeout for fifo out full");
+			break;
+		}
+
+		t = (len >= 4) ? 4 : len;
+
+		while (idx < t) {
+			if (!i && (pos >= tlen)) {
+				buf = dbuf;
+				pos = 0;
+				i = 1;
+			}
+			val |= buf[pos++] << (idx++ * 8);
+		}
+
+		writel(val, qup->base + QUP_OUT_FIFO_BASE);
+		idx  = 0;
+		val = 0;
+		len -= 4;
+	}
+
+	return 0;
+}
+
+static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+	u32 data_len = 0, tag_len;
+
+	tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
+
+	if (!(msg->flags & I2C_M_RD))
+		data_len = qup->blk.block_data_len[qup->blk.block_pos];
+
+	qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
+}
+
+static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
+				*msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_issue_xfer_v2(qup, msg);
+	else
+		qup_i2c_issue_write_v1(qup, msg);
+}
+
+static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+			     int run, int last)
 {
 	unsigned long left;
 	int ret;
@@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	qup->msg = msg;
 	qup->pos = 0;
 
+	if (qup->use_v2_tags)
+		qup_i2c_create_tag_v2(qup, msg, last);
+	else
+		qup->blk.blocks = 0;
+
 	enable_irq(qup->irq);
 
-	qup_i2c_set_write_mode(qup, msg);
+	qup_i2c_set_write_mode(qup, msg, run);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+	if (!run) {
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
+	}
 
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
@@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 			ret = -EIO;
 			goto err;
 		}
-	} while (qup->pos < msg->len);
+		qup->blk.block_pos++;
+	} while (qup->blk.block_pos < qup->blk.blocks);
 
 	/* Wait for the outstanding data in the fifo to drain */
-	ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
+	if (last)
+		ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
+					 ONE_BYTE);
 
 err:
 	disable_irq(qup->irq);
@@ -375,8 +557,17 @@ err:
 	return ret;
 }
 
-static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
+static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
 {
+	if (qup->use_v2_tags) {
+		len += qup->rx_tag_len;
+		if (run) {
+			len |= QUP_I2C_MX_CONFIG_DURING_RUN;
+			qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
+		}
+		writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
+	}
+
 	if (len < qup->in_fifo_sz) {
 		/* FIFO mode */
 		writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
@@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
 	}
 }
 
-static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
+				  struct i2c_msg *msg)
 {
 	u32 addr, len, val;
 
@@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	writel(val, qup->base + QUP_OUT_FIFO_BASE);
 }
 
+static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
+			       *msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_issue_xfer_v2(qup, msg);
+	else
+		qup_i2c_issue_read_v1(qup, msg);
+}
 
-static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
-	u32 opflags;
 	u32 val = 0;
 	int idx;
+	int len = msg->len + qup->rx_tag_len;
 
-	for (idx = 0; qup->pos < msg->len; idx++) {
+	for (idx = 0; qup->pos < len; idx++) {
 		if ((idx & 1) == 0) {
 			/* Check that FIFO have data */
-			opflags = readl(qup->base + QUP_OPERATIONAL);
-			if (!(opflags & QUP_IN_NOT_EMPTY))
+			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+				dev_err(qup->dev, "timeout for fifo not empty");
 				break;
-
+			}
 			/* Reading 2 words at time */
 			val = readl(qup->base + QUP_IN_FIFO_BASE);
 
@@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	}
 }
 
-static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
+				 struct i2c_msg *msg)
+{
+	u32 val;
+	int idx;
+	int pos = 0;
+	/* 2 extra bytes for read tags */
+	int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
+
+	while (pos < total) {
+		/* Check that FIFO have data */
+		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+			dev_err(qup->dev, "timeout for fifo not empty");
+			break;
+		}
+		val = readl(qup->base + QUP_IN_FIFO_BASE);
+
+		for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
+			/* first 2 bytes are tag bytes */
+			if (pos < 2)
+				continue;
+
+			if (pos >= total)
+				return;
+
+			msg->buf[qup->pos++] = val & 0xff;
+		}
+	}
+}
+
+static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
+			      struct i2c_msg *msg)
+{
+	if (qup->use_v2_tags)
+		qup_i2c_read_fifo_v2(qup, msg);
+	else
+		qup_i2c_read_fifo_v1(qup, msg);
+}
+
+static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
+			    int run, int last)
 {
 	unsigned long left;
 	int ret;
-
 	/*
 	 * The QUP block will issue a NACK and STOP on the bus when reaching
 	 * the end of the read, the length of the read is specified as one byte
@@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 
 	qup->msg = msg;
 	qup->pos  = 0;
+	if (qup->use_v2_tags)
+		qup_i2c_create_tag_v2(qup, msg, last);
+	else
+		qup->blk.blocks = 0;
 
 	enable_irq(qup->irq);
 
-	qup_i2c_set_read_mode(qup, msg->len);
+	qup_i2c_set_read_mode(qup, msg->len, run);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+	if (!run) {
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
+	}
 
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
-	ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
-	if (ret)
-		goto err;
+	do {
+		ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+		if (ret)
+			goto err;
 
-	qup_i2c_issue_read(qup, msg);
+		qup_i2c_issue_read(qup, msg);
 
-	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-	if (ret)
-		goto err;
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret)
+			goto err;
 
-	do {
 		left = wait_for_completion_timeout(&qup->xfer, HZ);
 		if (!left) {
 			writel(1, qup->base + QUP_SW_RESET);
@@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 		}
 
 		qup_i2c_read_fifo(qup, msg);
-	} while (qup->pos < msg->len);
+		qup->blk.block_pos++;
+	} while (qup->blk.block_pos < qup->blk.blocks);
 
 err:
 	disable_irq(qup->irq);
@@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx;
+	int ret, idx, last;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 		goto out;
 
 	/* Configure QUP as I2C mini core */
-	writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
+	if (qup->use_v2_tags) {
+		writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
+		writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
+	} else {
+		writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
+	}
 
 	for (idx = 0; idx < num; idx++) {
 		if (msgs[idx].len == 0) {
@@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			goto out;
 		}
 
+		reinit_completion(&qup->xfer);
+
+		last = (idx == (num - 1));
+
 		if (msgs[idx].flags & I2C_M_RD)
-			ret = qup_i2c_read_one(qup, &msgs[idx]);
+			ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
 		else
-			ret = qup_i2c_write_one(qup, &msgs[idx]);
+			ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
 
 		if (ret)
 			break;
+	}
 
+	if (!ret)
 		ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
-		if (ret)
-			break;
-	}
 
 	if (ret == 0)
 		ret = num;
 out:
 
+	if (qup->use_v2_tags) {
+		kfree(qup->tags);
+		kfree(qup->blk.block_tag_len);
+		kfree(qup->blk.block_data_len);
+	}
+
 	pm_runtime_mark_last_busy(qup->dev);
 	pm_runtime_put_autosuspend(qup->dev);
 
@@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
 	clk_prepare_enable(qup->pclk);
 }
 
+static const struct of_device_id qup_i2c_dt_match[] = {
+	{ .compatible = "qcom,i2c-qup-v1.1.1"},
+	{ .compatible = "qcom,i2c-qup-v2.1.1"},
+	{ .compatible = "qcom,i2c-qup-v2.2.1"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
+
 static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
 {
 	u32 config;
@@ -580,8 +848,9 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
+	int src_clk_freq, clk_freq_max;
 	u32 clk_freq = 100000;
+	const struct of_device_id *of_id;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 	if (!qup)
@@ -593,8 +862,19 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
 	of_property_read_u32(node, "clock-frequency", &clk_freq);
 
-	/* We support frequencies up to FAST Mode (400KHz) */
-	if (!clk_freq || clk_freq > 400000) {
+	of_id = of_match_node(qup_i2c_dt_match, node);
+
+	if (of_device_is_compatible(pdev->dev.of_node,
+				    "qcom,i2c-qup-v1.1.1")) {
+		qup->use_v2_tags = 0;
+		clk_freq_max = 400000;
+	} else {
+		qup->use_v2_tags = 1;
+		clk_freq_max = 3400000;
+	}
+
+	/* We support frequencies up to HIGH SPEED Mode (3400KHz) */
+	if (!clk_freq || clk_freq > clk_freq_max) {
 		dev_err(qup->dev, "clock frequency not supported %d\n",
 			clk_freq);
 		return -EINVAL;
@@ -672,8 +952,17 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
 	src_clk_freq = clk_get_rate(qup->clk);
-	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
-	hs_div = 3;
+	if (clk_freq > I2C_QUP_CLK_FAST_FREQ) {
+		fs_div = I2C_QUP_CLK_FAST_FREQ;
+		hs_div = (src_clk_freq / clk_freq) / 3;
+
+		qup->is_hs = 1;
+	} else {
+		fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+		hs_div = 3;
+	}
+
+	hs_div = min_t(int, hs_div, 0x7);
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
 
 	/*
@@ -770,14 +1059,6 @@ static const struct dev_pm_ops qup_i2c_qup_pm_ops = {
 		NULL)
 };
 
-static const struct of_device_id qup_i2c_dt_match[] = {
-	{ .compatible = "qcom,i2c-qup-v1.1.1" },
-	{ .compatible = "qcom,i2c-qup-v2.1.1" },
-	{ .compatible = "qcom,i2c-qup-v2.2.1" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
-
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 3/6] i2c: qup: Add bam dma capabilities
  2015-04-11  7:08 ` Sricharan R
  (?)
@ 2015-04-11  7:09     ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: sricharan-sgV2jX0FEOL9JmXXK+q4OQ

QUP cores can be attached to a BAM module, which acts as
a dma engine for the QUP core. When DMA with BAM is enabled,
the BAM consumer pipe transmitted data is written to the output FIFO
and the BAM producer pipe received data is read from the input FIFO.

With BAM capabilities, qup-i2c core can transfer more than 256 bytes,
without a 'stop' which is not possible otherwise.

Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
[V3] Addressed comments from Andy Gross <agross-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
     to use macros for qup_i2c_wait_ready function.

 drivers/i2c/busses/i2c-qup.c | 415 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 406 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 16a8f69..4463ff8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -25,6 +25,11 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/atomic.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL		0x018
 #define QUP_ERROR_FLAGS		0x01c
 #define QUP_ERROR_FLAGS_EN	0x020
+#define QUP_OPERATIONAL_MASK	0x028
 #define QUP_HW_VERSION		0x030
 #define QUP_MX_OUTPUT_CNT	0x100
 #define QUP_OUT_FIFO_BASE	0x110
@@ -53,6 +59,7 @@
 
 #define QUP_STATE_VALID		BIT(2)
 #define QUP_I2C_MAST_GEN	BIT(4)
+#define QUP_I2C_FLUSH		BIT(6)
 
 #define QUP_OPERATIONAL_RESET	0x000ff0
 #define QUP_I2C_STATUS_RESET	0xfffffc
@@ -78,7 +85,10 @@
 
 /* Packing/Unpacking words in FIFOs, and IO modes */
 #define QUP_OUTPUT_BLK_MODE	(1 << 10)
+#define QUP_OUTPUT_BAM_MODE	(3 << 10)
 #define QUP_INPUT_BLK_MODE	(1 << 12)
+#define QUP_INPUT_BAM_MODE	(3 << 12)
+#define QUP_BAM_MODE		(QUP_OUTPUT_BAM_MODE | QUP_INPUT_BAM_MODE)
 #define QUP_UNPACK_EN		BIT(14)
 #define QUP_PACK_EN		BIT(15)
 
@@ -105,6 +115,10 @@
 #define QUP_TAG_V2_DATARD              0x85
 #define QUP_TAG_V2_DATARD_STOP         0x87
 
+/* QUP BAM v2 tags */
+#define QUP_BAM_INPUT_EOT		0x93
+#define QUP_BAM_FLUSH_STOP		0x96
+
 /* frequency definitions for high speed and max speed */
 #define I2C_QUP_CLK_FAST_FREQ          1000000
 
@@ -121,6 +135,12 @@
 
 #define QUP_I2C_MX_CONFIG_DURING_RUN	BIT(31)
 
+#define MX_TX_RX_LEN			SZ_64K
+#define MX_BLOCKS			(MX_TX_RX_LEN / QUP_READ_LIMIT)
+
+/* Max timeout in ms for 32k bytes */
+#define TOUT_MAX			300
+
 struct qup_i2c_block {
 	int	blocks;
 	u8	*block_tag_len;
@@ -128,6 +148,23 @@ struct qup_i2c_block {
 	int	block_pos;
 };
 
+struct qup_i2c_tag {
+	u8 *start;
+	dma_addr_t addr;
+};
+
+struct qup_i2c_bam_rx {
+	struct	qup_i2c_tag scratch_tag;
+	struct	dma_chan *dma_rx;
+	struct	scatterlist *sg_rx;
+};
+
+struct qup_i2c_bam_tx {
+	struct	qup_i2c_tag footer_tag;
+	struct	dma_chan *dma_tx;
+	struct scatterlist *sg_tx;
+};
+
 struct qup_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
@@ -160,6 +197,12 @@ struct qup_i2c_dev {
 	/* QUP core errors */
 	u32			qup_err;
 
+	/* dma parameters */
+	bool			is_dma;
+	struct			dma_pool *dpool;
+	struct			qup_i2c_tag start_tag;
+	struct			qup_i2c_bam_rx brx;
+	struct			qup_i2c_bam_tx btx;
 	struct completion	xfer;
 };
 
@@ -236,6 +279,14 @@ static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state)
 	return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK);
 }
 
+static void qup_i2c_flush(struct qup_i2c_dev *qup)
+{
+	u32 val = readl(qup->base + QUP_STATE);
+
+	val |= QUP_I2C_FLUSH;
+	writel(val, qup->base + QUP_STATE);
+}
+
 static int qup_i2c_poll_state_valid(struct qup_i2c_dev *qup)
 {
 	return qup_i2c_poll_state_mask(qup, 0, 0);
@@ -446,7 +497,8 @@ static u32 qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
 	u8 *buf = tbuf;
 
 	while (len > 0) {
-		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, RESET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo out full");
 			break;
 		}
@@ -612,7 +664,8 @@ static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	for (idx = 0; qup->pos < len; idx++) {
 		if ((idx & 1) == 0) {
 			/* Check that FIFO have data */
-			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+					       4 * ONE_BYTE)) {
 				dev_err(qup->dev, "timeout for fifo not empty");
 				break;
 			}
@@ -637,7 +690,8 @@ static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 
 	while (pos < total) {
 		/* Check that FIFO have data */
-		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo not empty");
 			break;
 		}
@@ -736,12 +790,281 @@ err:
 	return ret;
 }
 
+static void qup_i2c_bam_cb(void *data)
+{
+	struct qup_i2c_dev *qup = data;
+
+	complete(&qup->xfer);
+}
+
+static int get_tag_code(struct i2c_msg *msg, int last)
+{
+	u8 op;
+
+       /* always issue stop for each read block */
+	if (last) {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD_STOP;
+		else
+			op = QUP_TAG_V2_DATAWR_STOP;
+	} else {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD;
+		else
+			op = QUP_TAG_V2_DATAWR;
+	}
+
+	return op;
+}
+
+static int get_start_tag(u8 *tag, struct i2c_msg *msg, int first, int last,
+			 int blen)
+{
+	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	u8 op;
+	int len = 0;
+
+	op = get_tag_code(msg, last);
+
+	if (first) {
+		tag[len++] = QUP_TAG_V2_START;
+		tag[len++] = addr & 0xff;
+		if (msg->flags & I2C_M_TEN)
+			tag[len++] = addr >> 8;
+	}
+	tag[len++] = op;
+
+	/* Length > 0 implies 256 bytes */
+	if (blen > QUP_READ_LIMIT)
+		blen = 0;
+
+	tag[len++] = blen;
+
+	if (msg->flags & I2C_M_RD & last) {
+		tag[len++] = QUP_BAM_INPUT_EOT;
+		tag[len++] = QUP_BAM_FLUSH_STOP;
+	}
+
+	return len;
+}
+
+void qup_sg_set_buf(struct scatterlist *sg, void *buf, struct qup_i2c_tag *tg,
+		    unsigned int buflen, struct qup_i2c_dev *qup,
+		    int map, int dir)
+{
+	sg_set_buf(sg, buf, buflen);
+	dma_map_sg(qup->dev, sg, 1, dir);
+
+	if (!map)
+		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
+}
+
+static void qup_i2c_rel_dma(struct qup_i2c_dev *qup)
+{
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+	qup->btx.dma_tx = NULL;
+	qup->brx.dma_rx = NULL;
+}
+
+static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
+{
+	if (!qup->btx.dma_tx) {
+		qup->btx.dma_tx = dma_request_slave_channel(qup->dev, "tx");
+		if (!qup->btx.dma_tx) {
+			dev_err(qup->dev, "\n tx channel not available");
+			return -ENODEV;
+		}
+	}
+
+	if (!qup->brx.dma_rx) {
+		qup->brx.dma_rx = dma_request_slave_channel(qup->dev, "rx");
+		if (!qup->brx.dma_rx) {
+			dev_err(qup->dev, "\n rx channel not available");
+			qup_i2c_rel_dma(qup);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+	struct dma_async_tx_descriptor *txd, *rxd = NULL;
+	int ret = 0;
+	dma_cookie_t cookie_rx, cookie_tx;
+	u32 rx_nents = 0, tx_nents = 0, len = 0;
+	/* QUP I2C read/write limit for single command is 256bytes max*/
+	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+	int rem = msg->len % QUP_READ_LIMIT;
+	int tlen, i = 0, tx_len = 0;
+
+	if (msg->flags & I2C_M_RD) {
+		tx_nents = 1;
+		rx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->brx.sg_rx, rx_nents);
+
+		while (i < blocks) {
+			/* transfer length set to '0' implies 256 bytes */
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len += get_start_tag(&qup->start_tag.start[len],
+					      msg, !i, (i == (blocks - 1)),
+					      tlen);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+				       &qup->brx.scratch_tag.start[0],
+				       &qup->brx.scratch_tag,
+				       2, qup, 0, 0);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i],
+				       NULL, tlen, qup, 1,
+				       DMA_FROM_DEVICE);
+
+			i++;
+		}
+
+		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
+		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
+			       &qup->start_tag, len, qup, 0, 0);
+		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+			       &qup->brx.scratch_tag.start[1],
+			       &qup->brx.scratch_tag, 2,
+			       qup, 0, 0);
+	} else {
+		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
+		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
+
+		tx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->btx.sg_tx, tx_nents);
+
+		while (i < blocks) {
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len = get_start_tag(&qup->start_tag.start[tx_len],
+					    msg, !i, (i == (blocks - 1)), tlen);
+
+			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+				       &qup->start_tag.start[tx_len],
+				       &qup->start_tag,
+				       len, qup, 0, 0);
+
+			tx_len += len;
+			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i], NULL,
+				       tlen, qup, 1, DMA_TO_DEVICE);
+			i++;
+		}
+		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+			       &qup->btx.footer_tag.start[0],
+			       &qup->btx.footer_tag, 2,
+			       qup, 0, 0);
+	}
+
+	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
+				      DMA_MEM_TO_DEV,
+				      DMA_PREP_INTERRUPT | DMA_PREP_FENCE);
+	if (!txd) {
+		dev_err(qup->dev, "failed to get tx desc\n");
+		ret = -EINVAL;
+		goto desc_err;
+	}
+
+	if (!rx_nents) {
+		txd->callback = qup_i2c_bam_cb;
+		txd->callback_param = qup;
+	}
+
+	cookie_tx = dmaengine_submit(txd);
+	dma_async_issue_pending(qup->btx.dma_tx);
+
+	if (rx_nents) {
+		rxd = dmaengine_prep_slave_sg(qup->brx.dma_rx, qup->brx.sg_rx,
+					      rx_nents, DMA_DEV_TO_MEM,
+					      DMA_PREP_INTERRUPT);
+
+		if (!rxd) {
+			dev_err(qup->dev, "failed to get rx desc\n");
+			ret = -EINVAL;
+
+			/* abort TX descriptors */
+			dmaengine_terminate_all(qup->btx.dma_tx);
+			goto desc_err;
+		}
+
+		rxd->callback = qup_i2c_bam_cb;
+		rxd->callback_param = qup;
+		cookie_rx = dmaengine_submit(rxd);
+		dma_async_issue_pending(qup->brx.dma_rx);
+	}
+
+	if (!wait_for_completion_timeout(&qup->xfer, TOUT_MAX * HZ)) {
+		dev_err(qup->dev, "normal trans timed out\n");
+		ret = -ETIMEDOUT;
+	}
+
+	if (ret || qup->bus_err || qup->qup_err) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			dev_err(qup->dev, "NACK from %x\n", msg->addr);
+		ret = -EIO;
+		qup_i2c_flush(qup);
+		qup_i2c_change_state(qup, QUP_RUN_STATE);
+
+		/* wait for remaining interrupts to occur */
+		if (!wait_for_completion_timeout(&qup->xfer, HZ))
+			dev_err(qup->dev, "flush timed out\n");
+
+		qup_i2c_rel_dma(qup);
+	}
+
+desc_err:
+	return ret;
+}
+
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+{
+	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
+	int ret = 0;
+
+	enable_irq(qup->irq);
+	if (qup_i2c_req_dma(qup))
+		goto out;
+
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
+	writel(0, qup->base + QUP_MX_INPUT_CNT);
+	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
+
+	/* set BAM mode */
+	writel(QUP_REPACK_EN | QUP_BAM_MODE, qup->base + QUP_IO_MODE);
+
+	/* mask fifo irqs */
+	writel((0x3 << 8), qup->base + QUP_OPERATIONAL_MASK);
+
+	/* set RUN STATE */
+	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+	if (ret)
+		goto out;
+
+	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+
+	qup->msg = msg;
+	ret = bam_do_xfer(qup, qup->msg);
+out:
+	disable_irq(qup->irq);
+
+	qup->msg = NULL;
+	return ret;
+}
+
 static int qup_i2c_xfer(struct i2c_adapter *adap,
 			struct i2c_msg msgs[],
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last;
+	int ret, idx, last, len;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -773,12 +1096,20 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		last = (idx == (num - 1));
+		len = (&msgs[idx])->len;
 
-		if (msgs[idx].flags & I2C_M_RD)
-			ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
-		else
-			ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
+		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
+		    (len > qup->out_fifo_sz)) {
+			ret = qup_bam_xfer(adap, &msgs[idx]);
+		} else {
+			last = (idx == (num - 1));
+			if (msgs[idx].flags & I2C_M_RD)
+				ret = qup_i2c_read_one(qup, &msgs[idx], idx,
+						       last);
+			else
+				ret = qup_i2c_write_one(qup, &msgs[idx], idx,
+							last);
+		}
 
 		if (ret)
 			break;
@@ -851,6 +1182,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	int src_clk_freq, clk_freq_max;
 	u32 clk_freq = 100000;
 	const struct of_device_id *of_id;
+	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 	if (!qup)
@@ -871,8 +1203,57 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	} else {
 		qup->use_v2_tags = 1;
 		clk_freq_max = 3400000;
+
+		if (qup_i2c_req_dma(qup))
+			goto nodma;
+
+		blocks = (MX_BLOCKS << 1) + 1;
+		qup->btx.sg_tx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->btx.sg_tx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->brx.sg_rx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
+		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
+					 size, 4, 0);
+
+		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
+						     &qup->start_tag.addr);
+		if (!qup->start_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->brx.scratch_tag.start = dma_pool_alloc(qup->dpool,
+							    GFP_KERNEL,
+						&qup->brx.scratch_tag.addr);
+
+		if (!qup->brx.scratch_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->btx.footer_tag.start = dma_pool_alloc(qup->dpool,
+							   GFP_KERNEL,
+						&qup->btx.footer_tag.addr);
+		if (!qup->btx.footer_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->is_dma = 1;
 	}
 
+nodma:
 	/* We support frequencies up to HIGH SPEED Mode (3400KHz) */
 	if (!clk_freq || clk_freq > clk_freq_max) {
 		dev_err(qup->dev, "clock frequency not supported %d\n",
@@ -997,6 +1378,11 @@ fail_runtime:
 	pm_runtime_disable(qup->dev);
 	pm_runtime_set_suspended(qup->dev);
 fail:
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+
 	qup_i2c_disable_clocks(qup);
 	return ret;
 }
@@ -1005,6 +1391,17 @@ static int qup_i2c_remove(struct platform_device *pdev)
 {
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
+	if (qup->is_dma) {
+		dma_pool_free(qup->dpool, qup->start_tag.start,
+			      qup->start_tag.addr);
+		dma_pool_free(qup->dpool, qup->brx.scratch_tag.start,
+			      qup->brx.scratch_tag.addr);
+		dma_pool_free(qup->dpool, qup->btx.footer_tag.start,
+			      qup->btx.footer_tag.addr);
+		dma_pool_destroy(qup->dpool);
+		dma_release_channel(qup->btx.dma_tx);
+		dma_release_channel(qup->brx.dma_rx);
+	}
 	disable_irq(qup->irq);
 	qup_i2c_disable_clocks(qup);
 	i2c_del_adapter(&qup->adap);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 3/6] i2c: qup: Add bam dma capabilities
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

QUP cores can be attached to a BAM module, which acts as
a dma engine for the QUP core. When DMA with BAM is enabled,
the BAM consumer pipe transmitted data is written to the output FIFO
and the BAM producer pipe received data is read from the input FIFO.

With BAM capabilities, qup-i2c core can transfer more than 256 bytes,
without a 'stop' which is not possible otherwise.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[V3] Addressed comments from Andy Gross <agross@codeaurora.org>
     to use macros for qup_i2c_wait_ready function.

 drivers/i2c/busses/i2c-qup.c | 415 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 406 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 16a8f69..4463ff8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -25,6 +25,11 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/atomic.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL		0x018
 #define QUP_ERROR_FLAGS		0x01c
 #define QUP_ERROR_FLAGS_EN	0x020
+#define QUP_OPERATIONAL_MASK	0x028
 #define QUP_HW_VERSION		0x030
 #define QUP_MX_OUTPUT_CNT	0x100
 #define QUP_OUT_FIFO_BASE	0x110
@@ -53,6 +59,7 @@
 
 #define QUP_STATE_VALID		BIT(2)
 #define QUP_I2C_MAST_GEN	BIT(4)
+#define QUP_I2C_FLUSH		BIT(6)
 
 #define QUP_OPERATIONAL_RESET	0x000ff0
 #define QUP_I2C_STATUS_RESET	0xfffffc
@@ -78,7 +85,10 @@
 
 /* Packing/Unpacking words in FIFOs, and IO modes */
 #define QUP_OUTPUT_BLK_MODE	(1 << 10)
+#define QUP_OUTPUT_BAM_MODE	(3 << 10)
 #define QUP_INPUT_BLK_MODE	(1 << 12)
+#define QUP_INPUT_BAM_MODE	(3 << 12)
+#define QUP_BAM_MODE		(QUP_OUTPUT_BAM_MODE | QUP_INPUT_BAM_MODE)
 #define QUP_UNPACK_EN		BIT(14)
 #define QUP_PACK_EN		BIT(15)
 
@@ -105,6 +115,10 @@
 #define QUP_TAG_V2_DATARD              0x85
 #define QUP_TAG_V2_DATARD_STOP         0x87
 
+/* QUP BAM v2 tags */
+#define QUP_BAM_INPUT_EOT		0x93
+#define QUP_BAM_FLUSH_STOP		0x96
+
 /* frequency definitions for high speed and max speed */
 #define I2C_QUP_CLK_FAST_FREQ          1000000
 
@@ -121,6 +135,12 @@
 
 #define QUP_I2C_MX_CONFIG_DURING_RUN	BIT(31)
 
+#define MX_TX_RX_LEN			SZ_64K
+#define MX_BLOCKS			(MX_TX_RX_LEN / QUP_READ_LIMIT)
+
+/* Max timeout in ms for 32k bytes */
+#define TOUT_MAX			300
+
 struct qup_i2c_block {
 	int	blocks;
 	u8	*block_tag_len;
@@ -128,6 +148,23 @@ struct qup_i2c_block {
 	int	block_pos;
 };
 
+struct qup_i2c_tag {
+	u8 *start;
+	dma_addr_t addr;
+};
+
+struct qup_i2c_bam_rx {
+	struct	qup_i2c_tag scratch_tag;
+	struct	dma_chan *dma_rx;
+	struct	scatterlist *sg_rx;
+};
+
+struct qup_i2c_bam_tx {
+	struct	qup_i2c_tag footer_tag;
+	struct	dma_chan *dma_tx;
+	struct scatterlist *sg_tx;
+};
+
 struct qup_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
@@ -160,6 +197,12 @@ struct qup_i2c_dev {
 	/* QUP core errors */
 	u32			qup_err;
 
+	/* dma parameters */
+	bool			is_dma;
+	struct			dma_pool *dpool;
+	struct			qup_i2c_tag start_tag;
+	struct			qup_i2c_bam_rx brx;
+	struct			qup_i2c_bam_tx btx;
 	struct completion	xfer;
 };
 
@@ -236,6 +279,14 @@ static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state)
 	return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK);
 }
 
+static void qup_i2c_flush(struct qup_i2c_dev *qup)
+{
+	u32 val = readl(qup->base + QUP_STATE);
+
+	val |= QUP_I2C_FLUSH;
+	writel(val, qup->base + QUP_STATE);
+}
+
 static int qup_i2c_poll_state_valid(struct qup_i2c_dev *qup)
 {
 	return qup_i2c_poll_state_mask(qup, 0, 0);
@@ -446,7 +497,8 @@ static u32 qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
 	u8 *buf = tbuf;
 
 	while (len > 0) {
-		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, RESET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo out full");
 			break;
 		}
@@ -612,7 +664,8 @@ static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	for (idx = 0; qup->pos < len; idx++) {
 		if ((idx & 1) == 0) {
 			/* Check that FIFO have data */
-			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+					       4 * ONE_BYTE)) {
 				dev_err(qup->dev, "timeout for fifo not empty");
 				break;
 			}
@@ -637,7 +690,8 @@ static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 
 	while (pos < total) {
 		/* Check that FIFO have data */
-		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo not empty");
 			break;
 		}
@@ -736,12 +790,281 @@ err:
 	return ret;
 }
 
+static void qup_i2c_bam_cb(void *data)
+{
+	struct qup_i2c_dev *qup = data;
+
+	complete(&qup->xfer);
+}
+
+static int get_tag_code(struct i2c_msg *msg, int last)
+{
+	u8 op;
+
+       /* always issue stop for each read block */
+	if (last) {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD_STOP;
+		else
+			op = QUP_TAG_V2_DATAWR_STOP;
+	} else {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD;
+		else
+			op = QUP_TAG_V2_DATAWR;
+	}
+
+	return op;
+}
+
+static int get_start_tag(u8 *tag, struct i2c_msg *msg, int first, int last,
+			 int blen)
+{
+	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	u8 op;
+	int len = 0;
+
+	op = get_tag_code(msg, last);
+
+	if (first) {
+		tag[len++] = QUP_TAG_V2_START;
+		tag[len++] = addr & 0xff;
+		if (msg->flags & I2C_M_TEN)
+			tag[len++] = addr >> 8;
+	}
+	tag[len++] = op;
+
+	/* Length > 0 implies 256 bytes */
+	if (blen > QUP_READ_LIMIT)
+		blen = 0;
+
+	tag[len++] = blen;
+
+	if (msg->flags & I2C_M_RD & last) {
+		tag[len++] = QUP_BAM_INPUT_EOT;
+		tag[len++] = QUP_BAM_FLUSH_STOP;
+	}
+
+	return len;
+}
+
+void qup_sg_set_buf(struct scatterlist *sg, void *buf, struct qup_i2c_tag *tg,
+		    unsigned int buflen, struct qup_i2c_dev *qup,
+		    int map, int dir)
+{
+	sg_set_buf(sg, buf, buflen);
+	dma_map_sg(qup->dev, sg, 1, dir);
+
+	if (!map)
+		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
+}
+
+static void qup_i2c_rel_dma(struct qup_i2c_dev *qup)
+{
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+	qup->btx.dma_tx = NULL;
+	qup->brx.dma_rx = NULL;
+}
+
+static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
+{
+	if (!qup->btx.dma_tx) {
+		qup->btx.dma_tx = dma_request_slave_channel(qup->dev, "tx");
+		if (!qup->btx.dma_tx) {
+			dev_err(qup->dev, "\n tx channel not available");
+			return -ENODEV;
+		}
+	}
+
+	if (!qup->brx.dma_rx) {
+		qup->brx.dma_rx = dma_request_slave_channel(qup->dev, "rx");
+		if (!qup->brx.dma_rx) {
+			dev_err(qup->dev, "\n rx channel not available");
+			qup_i2c_rel_dma(qup);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+	struct dma_async_tx_descriptor *txd, *rxd = NULL;
+	int ret = 0;
+	dma_cookie_t cookie_rx, cookie_tx;
+	u32 rx_nents = 0, tx_nents = 0, len = 0;
+	/* QUP I2C read/write limit for single command is 256bytes max*/
+	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+	int rem = msg->len % QUP_READ_LIMIT;
+	int tlen, i = 0, tx_len = 0;
+
+	if (msg->flags & I2C_M_RD) {
+		tx_nents = 1;
+		rx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->brx.sg_rx, rx_nents);
+
+		while (i < blocks) {
+			/* transfer length set to '0' implies 256 bytes */
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len += get_start_tag(&qup->start_tag.start[len],
+					      msg, !i, (i == (blocks - 1)),
+					      tlen);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+				       &qup->brx.scratch_tag.start[0],
+				       &qup->brx.scratch_tag,
+				       2, qup, 0, 0);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i],
+				       NULL, tlen, qup, 1,
+				       DMA_FROM_DEVICE);
+
+			i++;
+		}
+
+		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
+		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
+			       &qup->start_tag, len, qup, 0, 0);
+		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+			       &qup->brx.scratch_tag.start[1],
+			       &qup->brx.scratch_tag, 2,
+			       qup, 0, 0);
+	} else {
+		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
+		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
+
+		tx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->btx.sg_tx, tx_nents);
+
+		while (i < blocks) {
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len = get_start_tag(&qup->start_tag.start[tx_len],
+					    msg, !i, (i == (blocks - 1)), tlen);
+
+			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+				       &qup->start_tag.start[tx_len],
+				       &qup->start_tag,
+				       len, qup, 0, 0);
+
+			tx_len += len;
+			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i], NULL,
+				       tlen, qup, 1, DMA_TO_DEVICE);
+			i++;
+		}
+		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+			       &qup->btx.footer_tag.start[0],
+			       &qup->btx.footer_tag, 2,
+			       qup, 0, 0);
+	}
+
+	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
+				      DMA_MEM_TO_DEV,
+				      DMA_PREP_INTERRUPT | DMA_PREP_FENCE);
+	if (!txd) {
+		dev_err(qup->dev, "failed to get tx desc\n");
+		ret = -EINVAL;
+		goto desc_err;
+	}
+
+	if (!rx_nents) {
+		txd->callback = qup_i2c_bam_cb;
+		txd->callback_param = qup;
+	}
+
+	cookie_tx = dmaengine_submit(txd);
+	dma_async_issue_pending(qup->btx.dma_tx);
+
+	if (rx_nents) {
+		rxd = dmaengine_prep_slave_sg(qup->brx.dma_rx, qup->brx.sg_rx,
+					      rx_nents, DMA_DEV_TO_MEM,
+					      DMA_PREP_INTERRUPT);
+
+		if (!rxd) {
+			dev_err(qup->dev, "failed to get rx desc\n");
+			ret = -EINVAL;
+
+			/* abort TX descriptors */
+			dmaengine_terminate_all(qup->btx.dma_tx);
+			goto desc_err;
+		}
+
+		rxd->callback = qup_i2c_bam_cb;
+		rxd->callback_param = qup;
+		cookie_rx = dmaengine_submit(rxd);
+		dma_async_issue_pending(qup->brx.dma_rx);
+	}
+
+	if (!wait_for_completion_timeout(&qup->xfer, TOUT_MAX * HZ)) {
+		dev_err(qup->dev, "normal trans timed out\n");
+		ret = -ETIMEDOUT;
+	}
+
+	if (ret || qup->bus_err || qup->qup_err) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			dev_err(qup->dev, "NACK from %x\n", msg->addr);
+		ret = -EIO;
+		qup_i2c_flush(qup);
+		qup_i2c_change_state(qup, QUP_RUN_STATE);
+
+		/* wait for remaining interrupts to occur */
+		if (!wait_for_completion_timeout(&qup->xfer, HZ))
+			dev_err(qup->dev, "flush timed out\n");
+
+		qup_i2c_rel_dma(qup);
+	}
+
+desc_err:
+	return ret;
+}
+
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+{
+	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
+	int ret = 0;
+
+	enable_irq(qup->irq);
+	if (qup_i2c_req_dma(qup))
+		goto out;
+
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
+	writel(0, qup->base + QUP_MX_INPUT_CNT);
+	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
+
+	/* set BAM mode */
+	writel(QUP_REPACK_EN | QUP_BAM_MODE, qup->base + QUP_IO_MODE);
+
+	/* mask fifo irqs */
+	writel((0x3 << 8), qup->base + QUP_OPERATIONAL_MASK);
+
+	/* set RUN STATE */
+	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+	if (ret)
+		goto out;
+
+	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+
+	qup->msg = msg;
+	ret = bam_do_xfer(qup, qup->msg);
+out:
+	disable_irq(qup->irq);
+
+	qup->msg = NULL;
+	return ret;
+}
+
 static int qup_i2c_xfer(struct i2c_adapter *adap,
 			struct i2c_msg msgs[],
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last;
+	int ret, idx, last, len;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -773,12 +1096,20 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		last = (idx == (num - 1));
+		len = (&msgs[idx])->len;
 
-		if (msgs[idx].flags & I2C_M_RD)
-			ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
-		else
-			ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
+		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
+		    (len > qup->out_fifo_sz)) {
+			ret = qup_bam_xfer(adap, &msgs[idx]);
+		} else {
+			last = (idx == (num - 1));
+			if (msgs[idx].flags & I2C_M_RD)
+				ret = qup_i2c_read_one(qup, &msgs[idx], idx,
+						       last);
+			else
+				ret = qup_i2c_write_one(qup, &msgs[idx], idx,
+							last);
+		}
 
 		if (ret)
 			break;
@@ -851,6 +1182,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	int src_clk_freq, clk_freq_max;
 	u32 clk_freq = 100000;
 	const struct of_device_id *of_id;
+	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 	if (!qup)
@@ -871,8 +1203,57 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	} else {
 		qup->use_v2_tags = 1;
 		clk_freq_max = 3400000;
+
+		if (qup_i2c_req_dma(qup))
+			goto nodma;
+
+		blocks = (MX_BLOCKS << 1) + 1;
+		qup->btx.sg_tx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->btx.sg_tx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->brx.sg_rx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
+		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
+					 size, 4, 0);
+
+		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
+						     &qup->start_tag.addr);
+		if (!qup->start_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->brx.scratch_tag.start = dma_pool_alloc(qup->dpool,
+							    GFP_KERNEL,
+						&qup->brx.scratch_tag.addr);
+
+		if (!qup->brx.scratch_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->btx.footer_tag.start = dma_pool_alloc(qup->dpool,
+							   GFP_KERNEL,
+						&qup->btx.footer_tag.addr);
+		if (!qup->btx.footer_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->is_dma = 1;
 	}
 
+nodma:
 	/* We support frequencies up to HIGH SPEED Mode (3400KHz) */
 	if (!clk_freq || clk_freq > clk_freq_max) {
 		dev_err(qup->dev, "clock frequency not supported %d\n",
@@ -997,6 +1378,11 @@ fail_runtime:
 	pm_runtime_disable(qup->dev);
 	pm_runtime_set_suspended(qup->dev);
 fail:
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+
 	qup_i2c_disable_clocks(qup);
 	return ret;
 }
@@ -1005,6 +1391,17 @@ static int qup_i2c_remove(struct platform_device *pdev)
 {
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
+	if (qup->is_dma) {
+		dma_pool_free(qup->dpool, qup->start_tag.start,
+			      qup->start_tag.addr);
+		dma_pool_free(qup->dpool, qup->brx.scratch_tag.start,
+			      qup->brx.scratch_tag.addr);
+		dma_pool_free(qup->dpool, qup->btx.footer_tag.start,
+			      qup->btx.footer_tag.addr);
+		dma_pool_destroy(qup->dpool);
+		dma_release_channel(qup->btx.dma_tx);
+		dma_release_channel(qup->brx.dma_rx);
+	}
 	disable_irq(qup->irq);
 	qup_i2c_disable_clocks(qup);
 	i2c_del_adapter(&qup->adap);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 3/6] i2c: qup: Add bam dma capabilities
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

QUP cores can be attached to a BAM module, which acts as
a dma engine for the QUP core. When DMA with BAM is enabled,
the BAM consumer pipe transmitted data is written to the output FIFO
and the BAM producer pipe received data is read from the input FIFO.

With BAM capabilities, qup-i2c core can transfer more than 256 bytes,
without a 'stop' which is not possible otherwise.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
[V3] Addressed comments from Andy Gross <agross@codeaurora.org>
     to use macros for qup_i2c_wait_ready function.

 drivers/i2c/busses/i2c-qup.c | 415 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 406 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 16a8f69..4463ff8 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -25,6 +25,11 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/atomic.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL		0x018
 #define QUP_ERROR_FLAGS		0x01c
 #define QUP_ERROR_FLAGS_EN	0x020
+#define QUP_OPERATIONAL_MASK	0x028
 #define QUP_HW_VERSION		0x030
 #define QUP_MX_OUTPUT_CNT	0x100
 #define QUP_OUT_FIFO_BASE	0x110
@@ -53,6 +59,7 @@
 
 #define QUP_STATE_VALID		BIT(2)
 #define QUP_I2C_MAST_GEN	BIT(4)
+#define QUP_I2C_FLUSH		BIT(6)
 
 #define QUP_OPERATIONAL_RESET	0x000ff0
 #define QUP_I2C_STATUS_RESET	0xfffffc
@@ -78,7 +85,10 @@
 
 /* Packing/Unpacking words in FIFOs, and IO modes */
 #define QUP_OUTPUT_BLK_MODE	(1 << 10)
+#define QUP_OUTPUT_BAM_MODE	(3 << 10)
 #define QUP_INPUT_BLK_MODE	(1 << 12)
+#define QUP_INPUT_BAM_MODE	(3 << 12)
+#define QUP_BAM_MODE		(QUP_OUTPUT_BAM_MODE | QUP_INPUT_BAM_MODE)
 #define QUP_UNPACK_EN		BIT(14)
 #define QUP_PACK_EN		BIT(15)
 
@@ -105,6 +115,10 @@
 #define QUP_TAG_V2_DATARD              0x85
 #define QUP_TAG_V2_DATARD_STOP         0x87
 
+/* QUP BAM v2 tags */
+#define QUP_BAM_INPUT_EOT		0x93
+#define QUP_BAM_FLUSH_STOP		0x96
+
 /* frequency definitions for high speed and max speed */
 #define I2C_QUP_CLK_FAST_FREQ          1000000
 
@@ -121,6 +135,12 @@
 
 #define QUP_I2C_MX_CONFIG_DURING_RUN	BIT(31)
 
+#define MX_TX_RX_LEN			SZ_64K
+#define MX_BLOCKS			(MX_TX_RX_LEN / QUP_READ_LIMIT)
+
+/* Max timeout in ms for 32k bytes */
+#define TOUT_MAX			300
+
 struct qup_i2c_block {
 	int	blocks;
 	u8	*block_tag_len;
@@ -128,6 +148,23 @@ struct qup_i2c_block {
 	int	block_pos;
 };
 
+struct qup_i2c_tag {
+	u8 *start;
+	dma_addr_t addr;
+};
+
+struct qup_i2c_bam_rx {
+	struct	qup_i2c_tag scratch_tag;
+	struct	dma_chan *dma_rx;
+	struct	scatterlist *sg_rx;
+};
+
+struct qup_i2c_bam_tx {
+	struct	qup_i2c_tag footer_tag;
+	struct	dma_chan *dma_tx;
+	struct scatterlist *sg_tx;
+};
+
 struct qup_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
@@ -160,6 +197,12 @@ struct qup_i2c_dev {
 	/* QUP core errors */
 	u32			qup_err;
 
+	/* dma parameters */
+	bool			is_dma;
+	struct			dma_pool *dpool;
+	struct			qup_i2c_tag start_tag;
+	struct			qup_i2c_bam_rx brx;
+	struct			qup_i2c_bam_tx btx;
 	struct completion	xfer;
 };
 
@@ -236,6 +279,14 @@ static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state)
 	return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK);
 }
 
+static void qup_i2c_flush(struct qup_i2c_dev *qup)
+{
+	u32 val = readl(qup->base + QUP_STATE);
+
+	val |= QUP_I2C_FLUSH;
+	writel(val, qup->base + QUP_STATE);
+}
+
 static int qup_i2c_poll_state_valid(struct qup_i2c_dev *qup)
 {
 	return qup_i2c_poll_state_mask(qup, 0, 0);
@@ -446,7 +497,8 @@ static u32 qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
 	u8 *buf = tbuf;
 
 	while (len > 0) {
-		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, RESET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo out full");
 			break;
 		}
@@ -612,7 +664,8 @@ static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 	for (idx = 0; qup->pos < len; idx++) {
 		if ((idx & 1) == 0) {
 			/* Check that FIFO have data */
-			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+			if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+					       4 * ONE_BYTE)) {
 				dev_err(qup->dev, "timeout for fifo not empty");
 				break;
 			}
@@ -637,7 +690,8 @@ static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 
 	while (pos < total) {
 		/* Check that FIFO have data */
-		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
+		if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, SET_BIT,
+				       4 * ONE_BYTE)) {
 			dev_err(qup->dev, "timeout for fifo not empty");
 			break;
 		}
@@ -736,12 +790,281 @@ err:
 	return ret;
 }
 
+static void qup_i2c_bam_cb(void *data)
+{
+	struct qup_i2c_dev *qup = data;
+
+	complete(&qup->xfer);
+}
+
+static int get_tag_code(struct i2c_msg *msg, int last)
+{
+	u8 op;
+
+       /* always issue stop for each read block */
+	if (last) {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD_STOP;
+		else
+			op = QUP_TAG_V2_DATAWR_STOP;
+	} else {
+		if (msg->flags & I2C_M_RD)
+			op = QUP_TAG_V2_DATARD;
+		else
+			op = QUP_TAG_V2_DATAWR;
+	}
+
+	return op;
+}
+
+static int get_start_tag(u8 *tag, struct i2c_msg *msg, int first, int last,
+			 int blen)
+{
+	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	u8 op;
+	int len = 0;
+
+	op = get_tag_code(msg, last);
+
+	if (first) {
+		tag[len++] = QUP_TAG_V2_START;
+		tag[len++] = addr & 0xff;
+		if (msg->flags & I2C_M_TEN)
+			tag[len++] = addr >> 8;
+	}
+	tag[len++] = op;
+
+	/* Length > 0 implies 256 bytes */
+	if (blen > QUP_READ_LIMIT)
+		blen = 0;
+
+	tag[len++] = blen;
+
+	if (msg->flags & I2C_M_RD & last) {
+		tag[len++] = QUP_BAM_INPUT_EOT;
+		tag[len++] = QUP_BAM_FLUSH_STOP;
+	}
+
+	return len;
+}
+
+void qup_sg_set_buf(struct scatterlist *sg, void *buf, struct qup_i2c_tag *tg,
+		    unsigned int buflen, struct qup_i2c_dev *qup,
+		    int map, int dir)
+{
+	sg_set_buf(sg, buf, buflen);
+	dma_map_sg(qup->dev, sg, 1, dir);
+
+	if (!map)
+		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
+}
+
+static void qup_i2c_rel_dma(struct qup_i2c_dev *qup)
+{
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+	qup->btx.dma_tx = NULL;
+	qup->brx.dma_rx = NULL;
+}
+
+static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
+{
+	if (!qup->btx.dma_tx) {
+		qup->btx.dma_tx = dma_request_slave_channel(qup->dev, "tx");
+		if (!qup->btx.dma_tx) {
+			dev_err(qup->dev, "\n tx channel not available");
+			return -ENODEV;
+		}
+	}
+
+	if (!qup->brx.dma_rx) {
+		qup->brx.dma_rx = dma_request_slave_channel(qup->dev, "rx");
+		if (!qup->brx.dma_rx) {
+			dev_err(qup->dev, "\n rx channel not available");
+			qup_i2c_rel_dma(qup);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+	struct dma_async_tx_descriptor *txd, *rxd = NULL;
+	int ret = 0;
+	dma_cookie_t cookie_rx, cookie_tx;
+	u32 rx_nents = 0, tx_nents = 0, len = 0;
+	/* QUP I2C read/write limit for single command is 256bytes max*/
+	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+	int rem = msg->len % QUP_READ_LIMIT;
+	int tlen, i = 0, tx_len = 0;
+
+	if (msg->flags & I2C_M_RD) {
+		tx_nents = 1;
+		rx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->brx.sg_rx, rx_nents);
+
+		while (i < blocks) {
+			/* transfer length set to '0' implies 256 bytes */
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len += get_start_tag(&qup->start_tag.start[len],
+					      msg, !i, (i == (blocks - 1)),
+					      tlen);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+				       &qup->brx.scratch_tag.start[0],
+				       &qup->brx.scratch_tag,
+				       2, qup, 0, 0);
+
+			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i],
+				       NULL, tlen, qup, 1,
+				       DMA_FROM_DEVICE);
+
+			i++;
+		}
+
+		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
+		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
+			       &qup->start_tag, len, qup, 0, 0);
+		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
+			       &qup->brx.scratch_tag.start[1],
+			       &qup->brx.scratch_tag, 2,
+			       qup, 0, 0);
+	} else {
+		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
+		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
+
+		tx_nents = (blocks << 1) + 1;
+		sg_init_table(qup->btx.sg_tx, tx_nents);
+
+		while (i < blocks) {
+			tlen = (i == (blocks - 1)) ? rem : 0;
+			len = get_start_tag(&qup->start_tag.start[tx_len],
+					    msg, !i, (i == (blocks - 1)), tlen);
+
+			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+				       &qup->start_tag.start[tx_len],
+				       &qup->start_tag,
+				       len, qup, 0, 0);
+
+			tx_len += len;
+			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
+				       &msg->buf[QUP_READ_LIMIT * i], NULL,
+				       tlen, qup, 1, DMA_TO_DEVICE);
+			i++;
+		}
+		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
+			       &qup->btx.footer_tag.start[0],
+			       &qup->btx.footer_tag, 2,
+			       qup, 0, 0);
+	}
+
+	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
+				      DMA_MEM_TO_DEV,
+				      DMA_PREP_INTERRUPT | DMA_PREP_FENCE);
+	if (!txd) {
+		dev_err(qup->dev, "failed to get tx desc\n");
+		ret = -EINVAL;
+		goto desc_err;
+	}
+
+	if (!rx_nents) {
+		txd->callback = qup_i2c_bam_cb;
+		txd->callback_param = qup;
+	}
+
+	cookie_tx = dmaengine_submit(txd);
+	dma_async_issue_pending(qup->btx.dma_tx);
+
+	if (rx_nents) {
+		rxd = dmaengine_prep_slave_sg(qup->brx.dma_rx, qup->brx.sg_rx,
+					      rx_nents, DMA_DEV_TO_MEM,
+					      DMA_PREP_INTERRUPT);
+
+		if (!rxd) {
+			dev_err(qup->dev, "failed to get rx desc\n");
+			ret = -EINVAL;
+
+			/* abort TX descriptors */
+			dmaengine_terminate_all(qup->btx.dma_tx);
+			goto desc_err;
+		}
+
+		rxd->callback = qup_i2c_bam_cb;
+		rxd->callback_param = qup;
+		cookie_rx = dmaengine_submit(rxd);
+		dma_async_issue_pending(qup->brx.dma_rx);
+	}
+
+	if (!wait_for_completion_timeout(&qup->xfer, TOUT_MAX * HZ)) {
+		dev_err(qup->dev, "normal trans timed out\n");
+		ret = -ETIMEDOUT;
+	}
+
+	if (ret || qup->bus_err || qup->qup_err) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			dev_err(qup->dev, "NACK from %x\n", msg->addr);
+		ret = -EIO;
+		qup_i2c_flush(qup);
+		qup_i2c_change_state(qup, QUP_RUN_STATE);
+
+		/* wait for remaining interrupts to occur */
+		if (!wait_for_completion_timeout(&qup->xfer, HZ))
+			dev_err(qup->dev, "flush timed out\n");
+
+		qup_i2c_rel_dma(qup);
+	}
+
+desc_err:
+	return ret;
+}
+
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+{
+	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
+	int ret = 0;
+
+	enable_irq(qup->irq);
+	if (qup_i2c_req_dma(qup))
+		goto out;
+
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
+	writel(0, qup->base + QUP_MX_INPUT_CNT);
+	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
+
+	/* set BAM mode */
+	writel(QUP_REPACK_EN | QUP_BAM_MODE, qup->base + QUP_IO_MODE);
+
+	/* mask fifo irqs */
+	writel((0x3 << 8), qup->base + QUP_OPERATIONAL_MASK);
+
+	/* set RUN STATE */
+	ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+	if (ret)
+		goto out;
+
+	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+
+	qup->msg = msg;
+	ret = bam_do_xfer(qup, qup->msg);
+out:
+	disable_irq(qup->irq);
+
+	qup->msg = NULL;
+	return ret;
+}
+
 static int qup_i2c_xfer(struct i2c_adapter *adap,
 			struct i2c_msg msgs[],
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last;
+	int ret, idx, last, len;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -773,12 +1096,20 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		last = (idx == (num - 1));
+		len = (&msgs[idx])->len;
 
-		if (msgs[idx].flags & I2C_M_RD)
-			ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
-		else
-			ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
+		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
+		    (len > qup->out_fifo_sz)) {
+			ret = qup_bam_xfer(adap, &msgs[idx]);
+		} else {
+			last = (idx == (num - 1));
+			if (msgs[idx].flags & I2C_M_RD)
+				ret = qup_i2c_read_one(qup, &msgs[idx], idx,
+						       last);
+			else
+				ret = qup_i2c_write_one(qup, &msgs[idx], idx,
+							last);
+		}
 
 		if (ret)
 			break;
@@ -851,6 +1182,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	int src_clk_freq, clk_freq_max;
 	u32 clk_freq = 100000;
 	const struct of_device_id *of_id;
+	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 	if (!qup)
@@ -871,8 +1203,57 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	} else {
 		qup->use_v2_tags = 1;
 		clk_freq_max = 3400000;
+
+		if (qup_i2c_req_dma(qup))
+			goto nodma;
+
+		blocks = (MX_BLOCKS << 1) + 1;
+		qup->btx.sg_tx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->btx.sg_tx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
+					  sizeof(*qup->btx.sg_tx) * blocks,
+					  GFP_KERNEL);
+		if (!qup->brx.sg_rx) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
+		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
+					 size, 4, 0);
+
+		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
+						     &qup->start_tag.addr);
+		if (!qup->start_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->brx.scratch_tag.start = dma_pool_alloc(qup->dpool,
+							    GFP_KERNEL,
+						&qup->brx.scratch_tag.addr);
+
+		if (!qup->brx.scratch_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		qup->btx.footer_tag.start = dma_pool_alloc(qup->dpool,
+							   GFP_KERNEL,
+						&qup->btx.footer_tag.addr);
+		if (!qup->btx.footer_tag.start) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+		qup->is_dma = 1;
 	}
 
+nodma:
 	/* We support frequencies up to HIGH SPEED Mode (3400KHz) */
 	if (!clk_freq || clk_freq > clk_freq_max) {
 		dev_err(qup->dev, "clock frequency not supported %d\n",
@@ -997,6 +1378,11 @@ fail_runtime:
 	pm_runtime_disable(qup->dev);
 	pm_runtime_set_suspended(qup->dev);
 fail:
+	if (qup->btx.dma_tx)
+		dma_release_channel(qup->btx.dma_tx);
+	if (qup->brx.dma_rx)
+		dma_release_channel(qup->brx.dma_rx);
+
 	qup_i2c_disable_clocks(qup);
 	return ret;
 }
@@ -1005,6 +1391,17 @@ static int qup_i2c_remove(struct platform_device *pdev)
 {
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
+	if (qup->is_dma) {
+		dma_pool_free(qup->dpool, qup->start_tag.start,
+			      qup->start_tag.addr);
+		dma_pool_free(qup->dpool, qup->brx.scratch_tag.start,
+			      qup->brx.scratch_tag.addr);
+		dma_pool_free(qup->dpool, qup->btx.footer_tag.start,
+			      qup->btx.footer_tag.addr);
+		dma_pool_destroy(qup->dpool);
+		dma_release_channel(qup->btx.dma_tx);
+		dma_release_channel(qup->brx.dma_rx);
+	}
 	disable_irq(qup->irq);
 	qup_i2c_disable_clocks(qup);
 	i2c_del_adapter(&qup->adap);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
  2015-04-11  7:08 ` Sricharan R
  (?)
@ 2015-04-11  7:09     ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: sricharan-sgV2jX0FEOL9JmXXK+q4OQ

The definition of i2c_msg says that

"If this is the last message in a group, it is followed by a STOP.
  Otherwise it is followed by the next @i2c_msg transaction segment,
  beginning with a (repeated) START"

So the expectation is that there is no 'STOP' bit inbetween individual
i2c_msg segments with repeated 'START'. The QUP i2c hardware has no way
to inform that there should not be a 'STOP' at the end of transaction.
The only way to implement this is to coalesce all the i2c_msg in i2c_msgs
in to one transaction and transfer them. Adding the support for the same.

This is required for some clients like touchscreen which keeps
incrementing counts across individual transfers and 'STOP' bit inbetween
resets the counter, which is not required.

Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 drivers/i2c/busses/i2c-qup.c | 200 ++++++++++++++++++++++++++-----------------
 1 file changed, 122 insertions(+), 78 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4463ff8..1b71043 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -890,76 +890,94 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
 	return 0;
 }
 
-static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, int num)
 {
 	struct dma_async_tx_descriptor *txd, *rxd = NULL;
 	int ret = 0;
 	dma_cookie_t cookie_rx, cookie_tx;
-	u32 rx_nents = 0, tx_nents = 0, len = 0;
-	/* QUP I2C read/write limit for single command is 256bytes max*/
-	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
-	int rem = msg->len % QUP_READ_LIMIT;
-	int tlen, i = 0, tx_len = 0;
-
-	if (msg->flags & I2C_M_RD) {
-		tx_nents = 1;
-		rx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->brx.sg_rx, rx_nents);
-
-		while (i < blocks) {
-			/* transfer length set to '0' implies 256 bytes */
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len += get_start_tag(&qup->start_tag.start[len],
-					      msg, !i, (i == (blocks - 1)),
-					      tlen);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-				       &qup->brx.scratch_tag.start[0],
-				       &qup->brx.scratch_tag,
-				       2, qup, 0, 0);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i],
-				       NULL, tlen, qup, 1,
-				       DMA_FROM_DEVICE);
-
-			i++;
-		}
-
-		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
-		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
-			       &qup->start_tag, len, qup, 0, 0);
-		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-			       &qup->brx.scratch_tag.start[1],
-			       &qup->brx.scratch_tag, 2,
-			       qup, 0, 0);
-	} else {
-		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
-		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
-
-		tx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->btx.sg_tx, tx_nents);
-
-		while (i < blocks) {
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len = get_start_tag(&qup->start_tag.start[tx_len],
-					    msg, !i, (i == (blocks - 1)), tlen);
-
-			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-				       &qup->start_tag.start[tx_len],
-				       &qup->start_tag,
-				       len, qup, 0, 0);
-
-			tx_len += len;
-			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i], NULL,
-				       tlen, qup, 1, DMA_TO_DEVICE);
-			i++;
+	u32 rx_nents = 0, tx_nents = 0, len, blocks, rem, last;
+	u32 cur_rx_nents, cur_tx_nents;
+	u32 tlen, i, tx_len, tx_buf = 0, rx_buf = 0, off = 0;
+
+	while (num) {
+		blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+		rem = msg->len % QUP_READ_LIMIT;
+		i = 0, tx_len = 0, len = 0;
+
+		if (msg->flags & I2C_M_RD) {
+			cur_tx_nents = 1;
+			cur_rx_nents = (blocks * 2) + 1;
+			rx_nents += cur_rx_nents;
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				/* transfer length set to '0' implies 256
+				   bytes */
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len += get_start_tag(&qup->start_tag.start[off +
+									   len],
+						     msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &qup->brx.scratch_tag.start[0],
+					       &qup->brx.scratch_tag,
+					       2, qup, 0, 0);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup,
+					       1, DMA_FROM_DEVICE);
+				i++;
+			}
+			qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+				       &qup->start_tag.start[off],
+				       &qup->start_tag, len, qup, 0, 0);
+			off += len;
+			qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+				       &qup->brx.scratch_tag.start[1],
+				       &qup->brx.scratch_tag, 2,
+				       qup, 0, 0);
+		} else {
+			cur_tx_nents = (blocks * 2);
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len = get_start_tag(&qup->start_tag.start[off +
+									tx_len],
+						    msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->start_tag.start[off +
+								     tx_len],
+					       &qup->start_tag, len,
+					       qup, 0, 0);
+
+				tx_len += len;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup, 1,
+					       DMA_TO_DEVICE);
+				i++;
+			}
+			off += tx_len;
+
+			if (!(num - 1)) {
+				qup->btx.footer_tag.start[0] =
+							  QUP_BAM_FLUSH_STOP;
+				qup->btx.footer_tag.start[1] =
+							  QUP_BAM_FLUSH_STOP;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->btx.footer_tag.start[0],
+					       &qup->btx.footer_tag, 2,
+					       qup, 0, 0);
+				tx_nents += 1;
+			}
 		}
-		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-			       &qup->btx.footer_tag.start[0],
-			       &qup->btx.footer_tag, 2,
-			       qup, 0, 0);
+		msg++;
+		num--;
 	}
 
 	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
@@ -1006,10 +1024,20 @@ static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 
 	if (ret || qup->bus_err || qup->qup_err) {
 		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			msg--;
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
 		ret = -EIO;
+
+		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+			dev_err(qup->dev, "change to run state timed out");
+			return ret;
+		}
+
+		writel(QUP_BAM_INPUT_EOT, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
 		qup_i2c_flush(qup);
-		qup_i2c_change_state(qup, QUP_RUN_STATE);
 
 		/* wait for remaining interrupts to occur */
 		if (!wait_for_completion_timeout(&qup->xfer, HZ))
@@ -1022,7 +1050,7 @@ desc_err:
 	return ret;
 }
 
-static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret = 0;
@@ -1051,7 +1079,7 @@ static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
 	qup->msg = msg;
-	ret = bam_do_xfer(qup, qup->msg);
+	ret = bam_do_xfer(qup, qup->msg, num);
 out:
 	disable_irq(qup->irq);
 
@@ -1064,7 +1092,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last, len;
+	int ret, idx, last, use_dma = 0, len = 0;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -1083,12 +1111,27 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 		writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
 	}
 
-	for (idx = 0; idx < num; idx++) {
-		if (msgs[idx].len == 0) {
-			ret = -EINVAL;
-			goto out;
+	if ((qup->is_dma)) {
+		/* All i2c_msgs should be transferred using either dma or cpu */
+		for (idx = 0; idx < num; idx++) {
+			if (msgs[idx].len == 0) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (!len)
+				len = ((&msgs[idx])->len) > qup->out_fifo_sz;
+
+			if ((!is_vmalloc_addr((&msgs[idx])->buf)) && len) {
+				use_dma = 1;
+			 } else {
+				use_dma = 0;
+				break;
+			}
 		}
+	}
 
+	for (idx = 0; idx < num; idx++) {
 		if (qup_i2c_poll_state_i2c_master(qup)) {
 			ret = -EIO;
 			goto out;
@@ -1096,11 +1139,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		len = (&msgs[idx])->len;
-
-		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
-		    (len > qup->out_fifo_sz)) {
-			ret = qup_bam_xfer(adap, &msgs[idx]);
+		if (use_dma) {
+			ret = qup_bam_xfer(adap, &msgs[idx], num);
+			idx = num;
 		} else {
 			last = (idx == (num - 1));
 			if (msgs[idx].flags & I2C_M_RD)
@@ -1215,6 +1256,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->btx.sg_tx, blocks);
+
 		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
 					  sizeof(*qup->btx.sg_tx) * blocks,
 					  GFP_KERNEL);
@@ -1222,6 +1265,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->brx.sg_rx, blocks);
 
 		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
 		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

The definition of i2c_msg says that

"If this is the last message in a group, it is followed by a STOP.
  Otherwise it is followed by the next @i2c_msg transaction segment,
  beginning with a (repeated) START"

So the expectation is that there is no 'STOP' bit inbetween individual
i2c_msg segments with repeated 'START'. The QUP i2c hardware has no way
to inform that there should not be a 'STOP' at the end of transaction.
The only way to implement this is to coalesce all the i2c_msg in i2c_msgs
in to one transaction and transfer them. Adding the support for the same.

This is required for some clients like touchscreen which keeps
incrementing counts across individual transfers and 'STOP' bit inbetween
resets the counter, which is not required.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 200 ++++++++++++++++++++++++++-----------------
 1 file changed, 122 insertions(+), 78 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4463ff8..1b71043 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -890,76 +890,94 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
 	return 0;
 }
 
-static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, int num)
 {
 	struct dma_async_tx_descriptor *txd, *rxd = NULL;
 	int ret = 0;
 	dma_cookie_t cookie_rx, cookie_tx;
-	u32 rx_nents = 0, tx_nents = 0, len = 0;
-	/* QUP I2C read/write limit for single command is 256bytes max*/
-	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
-	int rem = msg->len % QUP_READ_LIMIT;
-	int tlen, i = 0, tx_len = 0;
-
-	if (msg->flags & I2C_M_RD) {
-		tx_nents = 1;
-		rx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->brx.sg_rx, rx_nents);
-
-		while (i < blocks) {
-			/* transfer length set to '0' implies 256 bytes */
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len += get_start_tag(&qup->start_tag.start[len],
-					      msg, !i, (i == (blocks - 1)),
-					      tlen);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-				       &qup->brx.scratch_tag.start[0],
-				       &qup->brx.scratch_tag,
-				       2, qup, 0, 0);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i],
-				       NULL, tlen, qup, 1,
-				       DMA_FROM_DEVICE);
-
-			i++;
-		}
-
-		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
-		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
-			       &qup->start_tag, len, qup, 0, 0);
-		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-			       &qup->brx.scratch_tag.start[1],
-			       &qup->brx.scratch_tag, 2,
-			       qup, 0, 0);
-	} else {
-		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
-		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
-
-		tx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->btx.sg_tx, tx_nents);
-
-		while (i < blocks) {
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len = get_start_tag(&qup->start_tag.start[tx_len],
-					    msg, !i, (i == (blocks - 1)), tlen);
-
-			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-				       &qup->start_tag.start[tx_len],
-				       &qup->start_tag,
-				       len, qup, 0, 0);
-
-			tx_len += len;
-			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i], NULL,
-				       tlen, qup, 1, DMA_TO_DEVICE);
-			i++;
+	u32 rx_nents = 0, tx_nents = 0, len, blocks, rem, last;
+	u32 cur_rx_nents, cur_tx_nents;
+	u32 tlen, i, tx_len, tx_buf = 0, rx_buf = 0, off = 0;
+
+	while (num) {
+		blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+		rem = msg->len % QUP_READ_LIMIT;
+		i = 0, tx_len = 0, len = 0;
+
+		if (msg->flags & I2C_M_RD) {
+			cur_tx_nents = 1;
+			cur_rx_nents = (blocks * 2) + 1;
+			rx_nents += cur_rx_nents;
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				/* transfer length set to '0' implies 256
+				   bytes */
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len += get_start_tag(&qup->start_tag.start[off +
+									   len],
+						     msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &qup->brx.scratch_tag.start[0],
+					       &qup->brx.scratch_tag,
+					       2, qup, 0, 0);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup,
+					       1, DMA_FROM_DEVICE);
+				i++;
+			}
+			qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+				       &qup->start_tag.start[off],
+				       &qup->start_tag, len, qup, 0, 0);
+			off += len;
+			qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+				       &qup->brx.scratch_tag.start[1],
+				       &qup->brx.scratch_tag, 2,
+				       qup, 0, 0);
+		} else {
+			cur_tx_nents = (blocks * 2);
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len = get_start_tag(&qup->start_tag.start[off +
+									tx_len],
+						    msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->start_tag.start[off +
+								     tx_len],
+					       &qup->start_tag, len,
+					       qup, 0, 0);
+
+				tx_len += len;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup, 1,
+					       DMA_TO_DEVICE);
+				i++;
+			}
+			off += tx_len;
+
+			if (!(num - 1)) {
+				qup->btx.footer_tag.start[0] =
+							  QUP_BAM_FLUSH_STOP;
+				qup->btx.footer_tag.start[1] =
+							  QUP_BAM_FLUSH_STOP;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->btx.footer_tag.start[0],
+					       &qup->btx.footer_tag, 2,
+					       qup, 0, 0);
+				tx_nents += 1;
+			}
 		}
-		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-			       &qup->btx.footer_tag.start[0],
-			       &qup->btx.footer_tag, 2,
-			       qup, 0, 0);
+		msg++;
+		num--;
 	}
 
 	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
@@ -1006,10 +1024,20 @@ static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 
 	if (ret || qup->bus_err || qup->qup_err) {
 		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			msg--;
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
 		ret = -EIO;
+
+		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+			dev_err(qup->dev, "change to run state timed out");
+			return ret;
+		}
+
+		writel(QUP_BAM_INPUT_EOT, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
 		qup_i2c_flush(qup);
-		qup_i2c_change_state(qup, QUP_RUN_STATE);
 
 		/* wait for remaining interrupts to occur */
 		if (!wait_for_completion_timeout(&qup->xfer, HZ))
@@ -1022,7 +1050,7 @@ desc_err:
 	return ret;
 }
 
-static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret = 0;
@@ -1051,7 +1079,7 @@ static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
 	qup->msg = msg;
-	ret = bam_do_xfer(qup, qup->msg);
+	ret = bam_do_xfer(qup, qup->msg, num);
 out:
 	disable_irq(qup->irq);
 
@@ -1064,7 +1092,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last, len;
+	int ret, idx, last, use_dma = 0, len = 0;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -1083,12 +1111,27 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 		writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
 	}
 
-	for (idx = 0; idx < num; idx++) {
-		if (msgs[idx].len == 0) {
-			ret = -EINVAL;
-			goto out;
+	if ((qup->is_dma)) {
+		/* All i2c_msgs should be transferred using either dma or cpu */
+		for (idx = 0; idx < num; idx++) {
+			if (msgs[idx].len == 0) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (!len)
+				len = ((&msgs[idx])->len) > qup->out_fifo_sz;
+
+			if ((!is_vmalloc_addr((&msgs[idx])->buf)) && len) {
+				use_dma = 1;
+			 } else {
+				use_dma = 0;
+				break;
+			}
 		}
+	}
 
+	for (idx = 0; idx < num; idx++) {
 		if (qup_i2c_poll_state_i2c_master(qup)) {
 			ret = -EIO;
 			goto out;
@@ -1096,11 +1139,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		len = (&msgs[idx])->len;
-
-		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
-		    (len > qup->out_fifo_sz)) {
-			ret = qup_bam_xfer(adap, &msgs[idx]);
+		if (use_dma) {
+			ret = qup_bam_xfer(adap, &msgs[idx], num);
+			idx = num;
 		} else {
 			last = (idx == (num - 1));
 			if (msgs[idx].flags & I2C_M_RD)
@@ -1215,6 +1256,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->btx.sg_tx, blocks);
+
 		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
 					  sizeof(*qup->btx.sg_tx) * blocks,
 					  GFP_KERNEL);
@@ -1222,6 +1265,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->brx.sg_rx, blocks);
 
 		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
 		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

The definition of i2c_msg says that

"If this is the last message in a group, it is followed by a STOP.
  Otherwise it is followed by the next @i2c_msg transaction segment,
  beginning with a (repeated) START"

So the expectation is that there is no 'STOP' bit inbetween individual
i2c_msg segments with repeated 'START'. The QUP i2c hardware has no way
to inform that there should not be a 'STOP' at the end of transaction.
The only way to implement this is to coalesce all the i2c_msg in i2c_msgs
in to one transaction and transfer them. Adding the support for the same.

This is required for some clients like touchscreen which keeps
incrementing counts across individual transfers and 'STOP' bit inbetween
resets the counter, which is not required.

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 200 ++++++++++++++++++++++++++-----------------
 1 file changed, 122 insertions(+), 78 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4463ff8..1b71043 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -890,76 +890,94 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
 	return 0;
 }
 
-static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, int num)
 {
 	struct dma_async_tx_descriptor *txd, *rxd = NULL;
 	int ret = 0;
 	dma_cookie_t cookie_rx, cookie_tx;
-	u32 rx_nents = 0, tx_nents = 0, len = 0;
-	/* QUP I2C read/write limit for single command is 256bytes max*/
-	int blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
-	int rem = msg->len % QUP_READ_LIMIT;
-	int tlen, i = 0, tx_len = 0;
-
-	if (msg->flags & I2C_M_RD) {
-		tx_nents = 1;
-		rx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->brx.sg_rx, rx_nents);
-
-		while (i < blocks) {
-			/* transfer length set to '0' implies 256 bytes */
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len += get_start_tag(&qup->start_tag.start[len],
-					      msg, !i, (i == (blocks - 1)),
-					      tlen);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-				       &qup->brx.scratch_tag.start[0],
-				       &qup->brx.scratch_tag,
-				       2, qup, 0, 0);
-
-			qup_sg_set_buf(&qup->brx.sg_rx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i],
-				       NULL, tlen, qup, 1,
-				       DMA_FROM_DEVICE);
-
-			i++;
-		}
-
-		sg_init_one(qup->btx.sg_tx, &qup->start_tag.start[0], len);
-		qup_sg_set_buf(qup->btx.sg_tx, &qup->start_tag.start[0],
-			       &qup->start_tag, len, qup, 0, 0);
-		qup_sg_set_buf(&qup->brx.sg_rx[i << 1],
-			       &qup->brx.scratch_tag.start[1],
-			       &qup->brx.scratch_tag, 2,
-			       qup, 0, 0);
-	} else {
-		qup->btx.footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
-		qup->btx.footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
-
-		tx_nents = (blocks << 1) + 1;
-		sg_init_table(qup->btx.sg_tx, tx_nents);
-
-		while (i < blocks) {
-			tlen = (i == (blocks - 1)) ? rem : 0;
-			len = get_start_tag(&qup->start_tag.start[tx_len],
-					    msg, !i, (i == (blocks - 1)), tlen);
-
-			qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-				       &qup->start_tag.start[tx_len],
-				       &qup->start_tag,
-				       len, qup, 0, 0);
-
-			tx_len += len;
-			qup_sg_set_buf(&qup->btx.sg_tx[(i << 1) + 1],
-				       &msg->buf[QUP_READ_LIMIT * i], NULL,
-				       tlen, qup, 1, DMA_TO_DEVICE);
-			i++;
+	u32 rx_nents = 0, tx_nents = 0, len, blocks, rem, last;
+	u32 cur_rx_nents, cur_tx_nents;
+	u32 tlen, i, tx_len, tx_buf = 0, rx_buf = 0, off = 0;
+
+	while (num) {
+		blocks = (msg->len + QUP_READ_LIMIT) / QUP_READ_LIMIT;
+		rem = msg->len % QUP_READ_LIMIT;
+		i = 0, tx_len = 0, len = 0;
+
+		if (msg->flags & I2C_M_RD) {
+			cur_tx_nents = 1;
+			cur_rx_nents = (blocks * 2) + 1;
+			rx_nents += cur_rx_nents;
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				/* transfer length set to '0' implies 256
+				   bytes */
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len += get_start_tag(&qup->start_tag.start[off +
+									   len],
+						     msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &qup->brx.scratch_tag.start[0],
+					       &qup->brx.scratch_tag,
+					       2, qup, 0, 0);
+
+				qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup,
+					       1, DMA_FROM_DEVICE);
+				i++;
+			}
+			qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+				       &qup->start_tag.start[off],
+				       &qup->start_tag, len, qup, 0, 0);
+			off += len;
+			qup_sg_set_buf(&qup->brx.sg_rx[rx_buf++],
+				       &qup->brx.scratch_tag.start[1],
+				       &qup->brx.scratch_tag, 2,
+				       qup, 0, 0);
+		} else {
+			cur_tx_nents = (blocks * 2);
+			tx_nents += cur_tx_nents;
+
+			while (i < blocks) {
+				tlen = (i == (blocks - 1)) ? rem : 0;
+				last = (i == (blocks - 1)) && !(num - 1);
+				len = get_start_tag(&qup->start_tag.start[off +
+									tx_len],
+						    msg, !i, last, tlen);
+
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->start_tag.start[off +
+								     tx_len],
+					       &qup->start_tag, len,
+					       qup, 0, 0);
+
+				tx_len += len;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &msg->buf[QUP_READ_LIMIT * i],
+					       NULL, tlen, qup, 1,
+					       DMA_TO_DEVICE);
+				i++;
+			}
+			off += tx_len;
+
+			if (!(num - 1)) {
+				qup->btx.footer_tag.start[0] =
+							  QUP_BAM_FLUSH_STOP;
+				qup->btx.footer_tag.start[1] =
+							  QUP_BAM_FLUSH_STOP;
+				qup_sg_set_buf(&qup->btx.sg_tx[tx_buf++],
+					       &qup->btx.footer_tag.start[0],
+					       &qup->btx.footer_tag, 2,
+					       qup, 0, 0);
+				tx_nents += 1;
+			}
 		}
-		qup_sg_set_buf(&qup->btx.sg_tx[i << 1],
-			       &qup->btx.footer_tag.start[0],
-			       &qup->btx.footer_tag, 2,
-			       qup, 0, 0);
+		msg++;
+		num--;
 	}
 
 	txd = dmaengine_prep_slave_sg(qup->btx.dma_tx, qup->btx.sg_tx, tx_nents,
@@ -1006,10 +1024,20 @@ static int bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 
 	if (ret || qup->bus_err || qup->qup_err) {
 		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			msg--;
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
 		ret = -EIO;
+
+		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+			dev_err(qup->dev, "change to run state timed out");
+			return ret;
+		}
+
+		writel(QUP_BAM_INPUT_EOT, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
 		qup_i2c_flush(qup);
-		qup_i2c_change_state(qup, QUP_RUN_STATE);
 
 		/* wait for remaining interrupts to occur */
 		if (!wait_for_completion_timeout(&qup->xfer, HZ))
@@ -1022,7 +1050,7 @@ desc_err:
 	return ret;
 }
 
-static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
+static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret = 0;
@@ -1051,7 +1079,7 @@ static int qup_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg)
 	writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
 
 	qup->msg = msg;
-	ret = bam_do_xfer(qup, qup->msg);
+	ret = bam_do_xfer(qup, qup->msg, num);
 out:
 	disable_irq(qup->irq);
 
@@ -1064,7 +1092,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			int num)
 {
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
-	int ret, idx, last, len;
+	int ret, idx, last, use_dma = 0, len = 0;
 
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
@@ -1083,12 +1111,27 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 		writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
 	}
 
-	for (idx = 0; idx < num; idx++) {
-		if (msgs[idx].len == 0) {
-			ret = -EINVAL;
-			goto out;
+	if ((qup->is_dma)) {
+		/* All i2c_msgs should be transferred using either dma or cpu */
+		for (idx = 0; idx < num; idx++) {
+			if (msgs[idx].len == 0) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (!len)
+				len = ((&msgs[idx])->len) > qup->out_fifo_sz;
+
+			if ((!is_vmalloc_addr((&msgs[idx])->buf)) && len) {
+				use_dma = 1;
+			 } else {
+				use_dma = 0;
+				break;
+			}
 		}
+	}
 
+	for (idx = 0; idx < num; idx++) {
 		if (qup_i2c_poll_state_i2c_master(qup)) {
 			ret = -EIO;
 			goto out;
@@ -1096,11 +1139,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 
 		reinit_completion(&qup->xfer);
 
-		len = (&msgs[idx])->len;
-
-		if ((qup->is_dma) && (!is_vmalloc_addr((&msgs[idx])->buf)) &&
-		    (len > qup->out_fifo_sz)) {
-			ret = qup_bam_xfer(adap, &msgs[idx]);
+		if (use_dma) {
+			ret = qup_bam_xfer(adap, &msgs[idx], num);
+			idx = num;
 		} else {
 			last = (idx == (num - 1));
 			if (msgs[idx].flags & I2C_M_RD)
@@ -1215,6 +1256,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->btx.sg_tx, blocks);
+
 		qup->brx.sg_rx = devm_kzalloc(&pdev->dev,
 					  sizeof(*qup->btx.sg_tx) * blocks,
 					  GFP_KERNEL);
@@ -1222,6 +1265,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 			ret = -ENOMEM;
 			goto fail;
 		}
+		sg_init_table(qup->brx.sg_rx, blocks);
 
 		size = sizeof(struct qup_i2c_tag) * (blocks + 3);
 		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
  2015-04-11  7:08 ` Sricharan R
  (?)
@ 2015-04-11  7:09     ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: sricharan-sgV2jX0FEOL9JmXXK+q4OQ

Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index e265ec1..2c26151 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/qcom,gcc-msm8974.h>
 #include "skeleton.dtsi"
 
@@ -247,5 +247,15 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
+
+		blsp2_dma: dma@f9944000 {
+			compatible = "qcom,bam-v1.4.0";
+			reg = <0xf9944000 0x19000>;
+			interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+		};
 	};
 };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index e265ec1..2c26151 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/qcom,gcc-msm8974.h>
 #include "skeleton.dtsi"
 
@@ -247,5 +247,15 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
+
+		blsp2_dma: dma@f9944000 {
+			compatible = "qcom,bam-v1.4.0";
+			reg = <0xf9944000 0x19000>;
+			interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+		};
 	};
 };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-11  7:09     ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index e265ec1..2c26151 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/qcom,gcc-msm8974.h>
 #include "skeleton.dtsi"
 
@@ -247,5 +247,15 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
+
+		blsp2_dma: dma at f9944000 {
+			compatible = "qcom,bam-v1.4.0";
+			reg = <0xf9944000 0x19000>;
+			interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+		};
 	};
 };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node
  2015-04-11  7:08 ` Sricharan R
@ 2015-04-11  7:09   ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: devicetree, linux-arm-msm, linux-kernel, linux-i2c, iivanov,
	agross, galak, dmaengine, linux-arm-kernel
  Cc: sricharan

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 2c26151..d741856 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -246,6 +246,8 @@
 			clock-names = "core", "iface";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			dmas = <&blsp2_dma 20>, <&blsp2_dma 21>;
+			dma-names = "tx", "rx";
 		};
 
 		blsp2_dma: dma@f9944000 {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH V3 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node
@ 2015-04-11  7:09   ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-11  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 2c26151..d741856 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -246,6 +246,8 @@
 			clock-names = "core", "iface";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			dmas = <&blsp2_dma 20>, <&blsp2_dma 21>;
+			dma-names = "tx", "rx";
 		};
 
 		blsp2_dma: dma at f9944000 {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
  2015-04-11  7:09     ` Sricharan R
  (?)
@ 2015-04-11 22:12         ` Sergei Shtylyov
  -1 siblings, 0 replies; 41+ messages in thread
From: Sergei Shtylyov @ 2015-04-11 22:12 UTC (permalink / raw)
  To: Sricharan R, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hello.

On 04/11/2015 10:09 AM, Sricharan R wrote:

> Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>   1 file changed, 11 insertions(+), 1 deletion(-)

> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
> index e265ec1..2c26151 100644
> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
[...]
> @@ -247,5 +247,15 @@
>   			#address-cells = <1>;
>   			#size-cells = <0>;
>   		};
> +
> +		blsp2_dma: dma@f9944000 {

    The ePAPR standard says that the node name should be "dma-controller", not 
just "dma".

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-11 22:12         ` Sergei Shtylyov
  0 siblings, 0 replies; 41+ messages in thread
From: Sergei Shtylyov @ 2015-04-11 22:12 UTC (permalink / raw)
  To: Sricharan R, devicetree, linux-arm-msm, linux-kernel, linux-i2c,
	iivanov, agross, galak, dmaengine, linux-arm-kernel

Hello.

On 04/11/2015 10:09 AM, Sricharan R wrote:

> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> ---
>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>   1 file changed, 11 insertions(+), 1 deletion(-)

> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
> index e265ec1..2c26151 100644
> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
[...]
> @@ -247,5 +247,15 @@
>   			#address-cells = <1>;
>   			#size-cells = <0>;
>   		};
> +
> +		blsp2_dma: dma@f9944000 {

    The ePAPR standard says that the node name should be "dma-controller", not 
just "dma".

[...]

WBR, Sergei


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-11 22:12         ` Sergei Shtylyov
  0 siblings, 0 replies; 41+ messages in thread
From: Sergei Shtylyov @ 2015-04-11 22:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 04/11/2015 10:09 AM, Sricharan R wrote:

> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> ---
>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>   1 file changed, 11 insertions(+), 1 deletion(-)

> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
> index e265ec1..2c26151 100644
> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
[...]
> @@ -247,5 +247,15 @@
>   			#address-cells = <1>;
>   			#size-cells = <0>;
>   		};
> +
> +		blsp2_dma: dma at f9944000 {

    The ePAPR standard says that the node name should be "dma-controller", not 
just "dma".

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
  2015-04-11 22:12         ` Sergei Shtylyov
  (?)
@ 2015-04-13  4:14             ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-13  4:14 UTC (permalink / raw)
  To: Sergei Shtylyov, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, iivanov-NEYub+7Iv8PQT0dZR+AlfA,
	agross-sgV2jX0FEOL9JmXXK+q4OQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi,

On 04/12/2015 03:42 AM, Sergei Shtylyov wrote:
> Hello.
>
> On 04/11/2015 10:09 AM, Sricharan R wrote:
>
>> Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> ---
>>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>>   1 file changed, 11 insertions(+), 1 deletion(-)
>
>> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> b/arch/arm/boot/dts/qcom-msm8974.dtsi
>> index e265ec1..2c26151 100644
>> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
> [...]
>> @@ -247,5 +247,15 @@
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>           };
>> +
>> +        blsp2_dma: dma@f9944000 {
>
>     The ePAPR standard says that the node name should be
> "dma-controller", not just "dma".
>
  Ok, will correct this.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-13  4:14             ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-13  4:14 UTC (permalink / raw)
  To: Sergei Shtylyov, devicetree, linux-arm-msm, linux-kernel,
	linux-i2c, iivanov, agross, galak, dmaengine, linux-arm-kernel

Hi,

On 04/12/2015 03:42 AM, Sergei Shtylyov wrote:
> Hello.
>
> On 04/11/2015 10:09 AM, Sricharan R wrote:
>
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> ---
>>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>>   1 file changed, 11 insertions(+), 1 deletion(-)
>
>> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> b/arch/arm/boot/dts/qcom-msm8974.dtsi
>> index e265ec1..2c26151 100644
>> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
> [...]
>> @@ -247,5 +247,15 @@
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>           };
>> +
>> +        blsp2_dma: dma@f9944000 {
>
>     The ePAPR standard says that the node name should be
> "dma-controller", not just "dma".
>
  Ok, will correct this.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node
@ 2015-04-13  4:14             ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-13  4:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 04/12/2015 03:42 AM, Sergei Shtylyov wrote:
> Hello.
>
> On 04/11/2015 10:09 AM, Sricharan R wrote:
>
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> ---
>>   arch/arm/boot/dts/qcom-msm8974.dtsi | 12 +++++++++++-
>>   1 file changed, 11 insertions(+), 1 deletion(-)
>
>> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> b/arch/arm/boot/dts/qcom-msm8974.dtsi
>> index e265ec1..2c26151 100644
>> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
>> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
> [...]
>> @@ -247,5 +247,15 @@
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>           };
>> +
>> +        blsp2_dma: dma at f9944000 {
>
>     The ePAPR standard says that the node name should be
> "dma-controller", not just "dma".
>
  Ok, will correct this.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-11  7:09   ` Sricharan R
@ 2015-04-14 15:16     ` Ivan T. Ivanov
  -1 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-14 15:16 UTC (permalink / raw)
  To: Sricharan R
  Cc: devicetree, linux-arm-msm, linux-kernel, linux-i2c, agross,
	galak, dmaengine, linux-arm-kernel


Hi Sricharan,

On Sat, 2015-04-11 at 12:39 +0530, Sricharan R wrote:
> From: Andy Gross <agross@codeaurora.org>
> 
> 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.
> 

But the read and write messages size QUP_READ_LIMIT?

> 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 <agross@codeaurora.org>
> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> ---
> [V3] Addressed comments from Andy Gross <agross@codeaurora.org>
>      to coalesce each i2c_msg in i2c_msgs as a single transfer.
>      Added macros to i2c_wait_ready function.
> 
>  drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
>  1 file changed, 337 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index 9ccf3e8..16a8f69 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -24,6 +24,7 @@
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> 
>  /* QUP Registers */
>  #define QUP_CONFIG             0x000
> @@ -42,6 +43,7 @@
>  #define QUP_IN_FIFO_BASE       0x218
>  #define QUP_I2C_CLK_CTL                0x400
>  #define QUP_I2C_STATUS         0x404
> +#define QUP_I2C_MASTER_GEN     0x408
> 
>  /* QUP States and reset values */
>  #define QUP_RESET_STATE                0
> @@ -69,6 +71,8 @@
>  #define QUP_CLOCK_AUTO_GATE    BIT(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)
> 
> @@ -80,17 +84,30 @@
> 
>  #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)
>  #define QUP_INPUT_BLOCK_SIZE(x)        (((x) >> 5) & 0x03)
>  #define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
> 
> -/* QUP tags */
> +/* QUP V1 tags */
>  #define QUP_TAG_START          (1 << 8)
>  #define QUP_TAG_DATA           (2 << 8)
>  #define QUP_TAG_STOP           (3 << 8)
>  #define QUP_TAG_REC            (4 << 8)
> 
> +/* QUP v2 tags */
> +#define QUP_TAG_V2_HS                  0xff
> +#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
> +
> +/* frequency definitions for high speed and max speed */
> +#define I2C_QUP_CLK_FAST_FREQ          1000000

This is fast mode, if I am not mistaken.

> +
>  /* Status, Error flags */
>  #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>  #define I2C_STATUS_BUS_ACTIVE          BIT(8)
> @@ -102,6 +119,15 @@
>  #define RESET_BIT                      0x0
>  #define ONE_BYTE                       0x1
> 
> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)

Could you explain what is this for?

> +
> +struct qup_i2c_block {
> +       int     blocks;
> +       u8      *block_tag_len;
> +       int     *block_data_len;
> +       int     block_pos;
> +};
> +
>  struct qup_i2c_dev {
>         struct device*dev;
>         void __iomem*base;
> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>         int     in_fifo_sz;
>         int     out_blk_sz;
>         int     in_blk_sz;
> -
> +       struct  qup_i2c_blockblk;
>         unsigned longone_byte_t;
> 
> +       int     is_hs;
> +       bool    use_v2_tags;
> +
> +       int     tx_tag_len;
> +       int     rx_tag_len;
> +       u8      *tags;
> +       int     tags_pos;
> +
>         struct i2c_msg*msg;
>         /* Current posion in user message buffer */
>         int     pos;
> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>         }
>  }

Is this better tag related fields grouping?

struct qup_i2c_tag_block {

        u8      tag[2];
        // int  tag_len; this is alway 2, or?
        int     data_len; // this could be zero, right?
};

> 
> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                       int run)

And 'run' stands for?

>  {
> -       /* Number of entries to shift out, including the start */
> -       int total = msg->len + 1;
> +       /* Total Number of entries to shift out, including the tags */
> +       int total;
> +
> +       if (qup->use_v2_tags) {
> +               total = msg->len + qup->tx_tag_len;
> +               if (run)
> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;

What?

> +       } else {
> +               total = msg->len + 1; /* plus start tag */
> +       }
> 
>         if (total < qup->out_fifo_sz) {
>                 /* FIFO mode */
> @@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
> *msg)
>         }
>  }
> 
> -static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>  {
>         u32 addr = msg->addr << 1;
>         u32 qup_tag;
> @@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg 
> *msg)
>         }
>  }
> 
> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
> +                                               struct i2c_msg *msg, int last)
> +{
> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
> +       int len = 0, prev_len = 0;
> +       int blocks = 0;
> +       int rem;
> +       int block_len = 0;
> +       int data_len;
> +
> +       qup->blk.block_pos = 0;
> +       qup->pos = 0;
> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
> +       rem = msg->len % QUP_READ_LIMIT;
> +
> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
> +                                               qup->blk.blocks, GFP_KERNEL);

Whouldn't be easy to kcalloc struct qup_i2c_tag_block?


Allocations could fail and memory is leaking here. 

> +
> +       while (blocks < qup->blk.blocks) {
> +               /* 0 is used to specify a READ_LIMIT of 256 bytes */
> +               data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
> +
> +               /* Send START and ADDR bytes only for the first block */
> +               if (!blocks) {
> +                       qup->tags[len++] = QUP_TAG_V2_START;
> +
> +                       if (qup->is_hs) {
> +                               qup->tags[len++] = QUP_TAG_V2_HS;
> +                               qup->tags[len++] = QUP_TAG_V2_START;
> +                       }
> +
> +                       qup->tags[len++] = addr & 0xff;
> +                       if (msg->flags & I2C_M_TEN)
> +                               qup->tags[len++] = addr >> 8;

I have counted 5 bytes for first block?

> +               }
> +
> +               /* Send _STOP commands for the last block */
> +               if ((blocks == (qup->blk.blocks - 1)) && last) {
> +                       if (msg->flags & I2C_M_RD)
> +                               qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +                       else
> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
> +               } else {
> +                       if (msg->flags & I2C_M_RD)
> +                               qup->tags[len++] = QUP_TAG_V2_DATARD;
> +                       else
> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR;
> +               }
> +
> +               qup->tags[len++] = data_len;
> +               block_len = len - prev_len;
> +               prev_len = len;
> +               qup->blk.block_tag_len[blocks] = block_len;
> +
> +               if (!data_len)
> +                       qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
> +               else
> +                       qup->blk.block_data_len[blocks] = data_len;
> +
> +               qup->tags_pos = 0;

Every time?

> +               blocks++;

Looks like 'for' cycle to me.

> +       }
> +
> +       qup->tx_tag_len = len;
> +
> +       if (msg->flags & I2C_M_RD)
> +               qup->rx_tag_len = (qup->blk.blocks * 2);
> +       else
> +               qup->rx_tag_len = 0;
> +}
> +
> +static u32 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;
> +
> +       while (len > 0) {
> +               if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
> +                       dev_err(qup->dev, "timeout for fifo out full");
> +                       break;

Error not propagated?

> +               }
> +
> +               t = (len >= 4) ? 4 : len;
> +
> +               while (idx < t) {
> +                       if (!i && (pos >= tlen)) {
> +                               buf = dbuf;
> +                               pos = 0;
> +                               i = 1;
> +                       }
> +                       val |= buf[pos++] << (idx++ * 8);
> +               }
> +
> +               writel(val, qup->base + QUP_OUT_FIFO_BASE);
> +               idx  = 0;
> +               val = 0;
> +               len -= 4;
> +       }
> +
> +       return 0;
> +}
> +
> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +{
> +       u32 data_len = 0, tag_len;
> +
> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> +
> +       if (!(msg->flags & I2C_M_RD))
> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> +
> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);

This assumes that writes are up to 256 bytes, and tags and data blocks
are completely written to FIFO buffer, right? 

> +}
> +
> +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
> +                               *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_issue_xfer_v2(qup, msg);
> +       else
> +               qup_i2c_issue_write_v1(qup, msg);
> +}
> +
> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                               int run, int last)
>  {
>         unsigned long left;
>         int ret;
> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         qup->msg = msg;
>         qup->pos = 0;
> 
> +       if (qup->use_v2_tags)
> +               qup_i2c_create_tag_v2(qup, msg, last);
> +       else
> +               qup->blk.blocks = 0;
> +
>         enable_irq(qup->irq);
> 
> -       qup_i2c_set_write_mode(qup, msg);
> +       qup_i2c_set_write_mode(qup, msg, run);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +       if (!run) {
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);

To run away, or not?

> +               if (ret)
> +                       goto err;
> +       }
> 
>         writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
> 
> @@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>                         ret = -EIO;
>                         goto err;
>                 }
> -       } while (qup->pos < msg->len);
> +               qup->blk.block_pos++;
> +       } while (qup->blk.block_pos < qup->blk.blocks);
> 
>         /* Wait for the outstanding data in the fifo to drain */
> -       ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
> +       if (last)
> +               ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
> +                                               ONE_BYTE);
> 
>  err:
>         disable_irq(qup->irq);
> @@ -375,8 +557,17 @@ err:
>         return ret;
>  }
> 
> -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
> +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
>  {
> +       if (qup->use_v2_tags) {
> +               len += qup->rx_tag_len;
> +               if (run) {
> +                       len |= QUP_I2C_MX_CONFIG_DURING_RUN;

Again? It looks like some kind of magic, to trick the controller
that there are more bytes to transfer, or? 

> +                       qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
> +               }
> +               writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
> +       }
> +
>         if (len < qup->in_fifo_sz) {
>                 /* FIFO mode */
>                 writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
> @@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>         }
>  }
> 
> -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
> +                                               struct i2c_msg *msg)
>  {
>         u32 addr, len, val;
> 
> @@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         writel(val, qup->base + QUP_OUT_FIFO_BASE);
>  }
> 
> +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
> +                                                                               *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_issue_xfer_v2(qup, msg);
> +       else
> +               qup_i2c_issue_read_v1(qup, msg);
> +}
> 
> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>  {
> -       u32 opflags;
>         u32 val = 0;
>         int idx;
> +       int len = msg->len + qup->rx_tag_len;

Is this intentional?

> 
> -       for (idx = 0; qup->pos < msg->len; idx++) {
> +       for (idx = 0; qup->pos < len; idx++) {
>                 if ((idx & 1) == 0) {
>                         /* Check that FIFO have data */
> -                       opflags = readl(qup->base + QUP_OPERATIONAL);
> -                       if (!(opflags & QUP_IN_NOT_EMPTY))
> +                       if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {

This should be part of the first patch.

> +                               dev_err(qup->dev, "timeout for fifo not empty");
>                                 break;
> -
> +                       }
>                         /* Reading 2 words at time */
>                         val = readl(qup->base + QUP_IN_FIFO_BASE);
> 
> @@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         }
>  }
> 
> -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
> +                                       struct i2c_msg *msg)
> +{
> +       u32 val;
> +       int idx;
> +       int pos = 0;
> +       /* 2 extra bytes for read tags */
> +       int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
> +
> +       while (pos < total) {
> +               /* Check that FIFO have data */
> +               if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
> +                       dev_err(qup->dev, "timeout for fifo not empty");
> +                       break;

Error not propagated.

> +               }
> +               val = readl(qup->base + QUP_IN_FIFO_BASE);
> +
> +               for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
> +                       /* first 2 bytes are tag bytes */
> +                       if (pos < 2)
> +                               continue;
> +
> +                       if (pos >= total)
> +                               return;
> +
> +                       msg->buf[qup->pos++] = val & 0xff;
> +               }
> +       }
> +}
> +
> +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
> +                                                                       struct i2c_msg *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_read_fifo_v2(qup, msg);
> +       else
> +               qup_i2c_read_fifo_v1(qup, msg);
> +}
> +
> +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                       int run, int last)
>  {
>         unsigned long left;
>         int ret;
> -
>         /*
>                 * The QUP block will issue a NACK and STOP on the bus when reaching
>                 * the end of the read, the length of the read is specified as one byte
> @@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> 
>         qup->msg = msg;
>         qup->pos  = 0;
> +       if (qup->use_v2_tags)
> +               qup_i2c_create_tag_v2(qup, msg, last);
> +       else
> +               qup->blk.blocks = 0;
> 
>         enable_irq(qup->irq);
> 
> -       qup_i2c_set_read_mode(qup, msg->len);
> +       qup_i2c_set_read_mode(qup, msg->len, run);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +       if (!run) {
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);

If !run, place controller in RUN state?

> +               if (ret)
> +                       goto err;
> +       }
> 
>         writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
> 
> -       ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
> -       if (ret)
> -               goto err;
> +       do {
> +               ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
> +               if (ret)
> +                       goto err;
> 
> -       qup_i2c_issue_read(qup, msg);
> +               qup_i2c_issue_read(qup, msg);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> +               if (ret)
> +                       goto err;
> 
> -       do {
>                 left = wait_for_completion_timeout(&qup->xfer, HZ);
>                 if (!left) {
>                         writel(1, qup->base + QUP_SW_RESET);
> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>                 }
> 
>                 qup_i2c_read_fifo(qup, msg);
> -       } while (qup->pos < msg->len);
> +               qup->blk.block_pos++;

This should not be incremented, unless we really have read this block.

> +       } while (qup->blk.block_pos < qup->blk.blocks);
> 
>  err:
>         disable_irq(qup->irq);
> @@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                         int num)
>  {
>         struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
> -       int ret, idx;
> +       int ret, idx, last;
> 
>         ret = pm_runtime_get_sync(qup->dev);
>         if (ret < 0)
> @@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                 goto out;
> 
>         /* Configure QUP as I2C mini core */
> -       writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
> +       if (qup->use_v2_tags) {
> +               writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
> +               writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
> +       } else {
> +               writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
> +       }
> 
>         for (idx = 0; idx < num; idx++) {
>                 if (msgs[idx].len == 0) {
> @@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                         goto out;
>                 }
> 
> +               reinit_completion(&qup->xfer);
> +
> +               last = (idx == (num - 1));
> +
>                 if (msgs[idx].flags & I2C_M_RD)
> -                       ret = qup_i2c_read_one(qup, &msgs[idx]);
> +                       ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
>                 else
> -                       ret = qup_i2c_write_one(qup, &msgs[idx]);
> +                       ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
> 
>                 if (ret)
>                         break;
> +       }
> 
> +       if (!ret)
>                 ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
> -               if (ret)
> -                       break;
> -       }
> 
>         if (ret == 0)
>                 ret = num;
>  out:
> 
> +       if (qup->use_v2_tags) {
> +               kfree(qup->tags);
> +               kfree(qup->blk.block_tag_len);
> +               kfree(qup->blk.block_data_len);
> +       }
> +
>         pm_runtime_mark_last_busy(qup->dev);
>         pm_runtime_put_autosuspend(qup->dev);
> 
> @@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
>         clk_prepare_enable(qup->pclk);
>  }
> 
> +static const struct of_device_id qup_i2c_dt_match[] = {
> +       { .compatible = "qcom,i2c-qup-v1.1.1"},
> +       { .compatible = "qcom,i2c-qup-v2.1.1"},
> +       { .compatible = "qcom,i2c-qup-v2.2.1"},

Space before closing brace, please.

I am starting to think that it will be more readable
if we just define qup_i2c_algo_v2 and use it, if 
controller is v2 and upwards?

Ivan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-14 15:16     ` Ivan T. Ivanov
  0 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-14 15:16 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Sricharan,

On Sat, 2015-04-11 at 12:39 +0530, Sricharan R wrote:
> From: Andy Gross <agross@codeaurora.org>
> 
> 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.
> 

But the read and write messages size QUP_READ_LIMIT?

> 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 <agross@codeaurora.org>
> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> ---
> [V3] Addressed comments from Andy Gross <agross@codeaurora.org>
>      to coalesce each i2c_msg in i2c_msgs as a single transfer.
>      Added macros to i2c_wait_ready function.
> 
>  drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
>  1 file changed, 337 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index 9ccf3e8..16a8f69 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -24,6 +24,7 @@
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> 
>  /* QUP Registers */
>  #define QUP_CONFIG             0x000
> @@ -42,6 +43,7 @@
>  #define QUP_IN_FIFO_BASE       0x218
>  #define QUP_I2C_CLK_CTL                0x400
>  #define QUP_I2C_STATUS         0x404
> +#define QUP_I2C_MASTER_GEN     0x408
> 
>  /* QUP States and reset values */
>  #define QUP_RESET_STATE                0
> @@ -69,6 +71,8 @@
>  #define QUP_CLOCK_AUTO_GATE    BIT(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)
> 
> @@ -80,17 +84,30 @@
> 
>  #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)
>  #define QUP_INPUT_BLOCK_SIZE(x)        (((x) >> 5) & 0x03)
>  #define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
> 
> -/* QUP tags */
> +/* QUP V1 tags */
>  #define QUP_TAG_START          (1 << 8)
>  #define QUP_TAG_DATA           (2 << 8)
>  #define QUP_TAG_STOP           (3 << 8)
>  #define QUP_TAG_REC            (4 << 8)
> 
> +/* QUP v2 tags */
> +#define QUP_TAG_V2_HS                  0xff
> +#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
> +
> +/* frequency definitions for high speed and max speed */
> +#define I2C_QUP_CLK_FAST_FREQ          1000000

This is fast mode, if I am not mistaken.

> +
>  /* Status, Error flags */
>  #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>  #define I2C_STATUS_BUS_ACTIVE          BIT(8)
> @@ -102,6 +119,15 @@
>  #define RESET_BIT                      0x0
>  #define ONE_BYTE                       0x1
> 
> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)

Could you explain what is this for?

> +
> +struct qup_i2c_block {
> +       int     blocks;
> +       u8      *block_tag_len;
> +       int     *block_data_len;
> +       int     block_pos;
> +};
> +
>  struct qup_i2c_dev {
>         struct device*dev;
>         void __iomem*base;
> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>         int     in_fifo_sz;
>         int     out_blk_sz;
>         int     in_blk_sz;
> -
> +       struct  qup_i2c_blockblk;
>         unsigned longone_byte_t;
> 
> +       int     is_hs;
> +       bool    use_v2_tags;
> +
> +       int     tx_tag_len;
> +       int     rx_tag_len;
> +       u8      *tags;
> +       int     tags_pos;
> +
>         struct i2c_msg*msg;
>         /* Current posion in user message buffer */
>         int     pos;
> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>         }
>  }

Is this better tag related fields grouping?

struct qup_i2c_tag_block {

        u8      tag[2];
        // int  tag_len; this is alway 2, or?
        int     data_len; // this could be zero, right?
};

> 
> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                       int run)

And 'run' stands for?

>  {
> -       /* Number of entries to shift out, including the start */
> -       int total = msg->len + 1;
> +       /* Total Number of entries to shift out, including the tags */
> +       int total;
> +
> +       if (qup->use_v2_tags) {
> +               total = msg->len + qup->tx_tag_len;
> +               if (run)
> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;

What?

> +       } else {
> +               total = msg->len + 1; /* plus start tag */
> +       }
> 
>         if (total < qup->out_fifo_sz) {
>                 /* FIFO mode */
> @@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
> *msg)
>         }
>  }
> 
> -static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>  {
>         u32 addr = msg->addr << 1;
>         u32 qup_tag;
> @@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg 
> *msg)
>         }
>  }
> 
> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
> +                                               struct i2c_msg *msg, int last)
> +{
> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
> +       int len = 0, prev_len = 0;
> +       int blocks = 0;
> +       int rem;
> +       int block_len = 0;
> +       int data_len;
> +
> +       qup->blk.block_pos = 0;
> +       qup->pos = 0;
> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
> +       rem = msg->len % QUP_READ_LIMIT;
> +
> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
> +                                               qup->blk.blocks, GFP_KERNEL);

Whouldn't be easy to kcalloc struct qup_i2c_tag_block?


Allocations could fail and memory is leaking here. 

> +
> +       while (blocks < qup->blk.blocks) {
> +               /* 0 is used to specify a READ_LIMIT of 256 bytes */
> +               data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
> +
> +               /* Send START and ADDR bytes only for the first block */
> +               if (!blocks) {
> +                       qup->tags[len++] = QUP_TAG_V2_START;
> +
> +                       if (qup->is_hs) {
> +                               qup->tags[len++] = QUP_TAG_V2_HS;
> +                               qup->tags[len++] = QUP_TAG_V2_START;
> +                       }
> +
> +                       qup->tags[len++] = addr & 0xff;
> +                       if (msg->flags & I2C_M_TEN)
> +                               qup->tags[len++] = addr >> 8;

I have counted 5 bytes for first block?

> +               }
> +
> +               /* Send _STOP commands for the last block */
> +               if ((blocks == (qup->blk.blocks - 1)) && last) {
> +                       if (msg->flags & I2C_M_RD)
> +                               qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +                       else
> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
> +               } else {
> +                       if (msg->flags & I2C_M_RD)
> +                               qup->tags[len++] = QUP_TAG_V2_DATARD;
> +                       else
> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR;
> +               }
> +
> +               qup->tags[len++] = data_len;
> +               block_len = len - prev_len;
> +               prev_len = len;
> +               qup->blk.block_tag_len[blocks] = block_len;
> +
> +               if (!data_len)
> +                       qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
> +               else
> +                       qup->blk.block_data_len[blocks] = data_len;
> +
> +               qup->tags_pos = 0;

Every time?

> +               blocks++;

Looks like 'for' cycle to me.

> +       }
> +
> +       qup->tx_tag_len = len;
> +
> +       if (msg->flags & I2C_M_RD)
> +               qup->rx_tag_len = (qup->blk.blocks * 2);
> +       else
> +               qup->rx_tag_len = 0;
> +}
> +
> +static u32 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;
> +
> +       while (len > 0) {
> +               if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
> +                       dev_err(qup->dev, "timeout for fifo out full");
> +                       break;

Error not propagated?

> +               }
> +
> +               t = (len >= 4) ? 4 : len;
> +
> +               while (idx < t) {
> +                       if (!i && (pos >= tlen)) {
> +                               buf = dbuf;
> +                               pos = 0;
> +                               i = 1;
> +                       }
> +                       val |= buf[pos++] << (idx++ * 8);
> +               }
> +
> +               writel(val, qup->base + QUP_OUT_FIFO_BASE);
> +               idx  = 0;
> +               val = 0;
> +               len -= 4;
> +       }
> +
> +       return 0;
> +}
> +
> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +{
> +       u32 data_len = 0, tag_len;
> +
> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> +
> +       if (!(msg->flags & I2C_M_RD))
> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> +
> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);

This assumes that writes are up to 256 bytes, and tags and data blocks
are completely written to FIFO buffer, right? 

> +}
> +
> +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
> +                               *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_issue_xfer_v2(qup, msg);
> +       else
> +               qup_i2c_issue_write_v1(qup, msg);
> +}
> +
> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                               int run, int last)
>  {
>         unsigned long left;
>         int ret;
> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         qup->msg = msg;
>         qup->pos = 0;
> 
> +       if (qup->use_v2_tags)
> +               qup_i2c_create_tag_v2(qup, msg, last);
> +       else
> +               qup->blk.blocks = 0;
> +
>         enable_irq(qup->irq);
> 
> -       qup_i2c_set_write_mode(qup, msg);
> +       qup_i2c_set_write_mode(qup, msg, run);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +       if (!run) {
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);

To run away, or not?

> +               if (ret)
> +                       goto err;
> +       }
> 
>         writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
> 
> @@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>                         ret = -EIO;
>                         goto err;
>                 }
> -       } while (qup->pos < msg->len);
> +               qup->blk.block_pos++;
> +       } while (qup->blk.block_pos < qup->blk.blocks);
> 
>         /* Wait for the outstanding data in the fifo to drain */
> -       ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
> +       if (last)
> +               ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
> +                                               ONE_BYTE);
> 
>  err:
>         disable_irq(qup->irq);
> @@ -375,8 +557,17 @@ err:
>         return ret;
>  }
> 
> -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
> +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
>  {
> +       if (qup->use_v2_tags) {
> +               len += qup->rx_tag_len;
> +               if (run) {
> +                       len |= QUP_I2C_MX_CONFIG_DURING_RUN;

Again? It looks like some kind of magic, to trick the controller
that there are more bytes to transfer, or? 

> +                       qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
> +               }
> +               writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
> +       }
> +
>         if (len < qup->in_fifo_sz) {
>                 /* FIFO mode */
>                 writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
> @@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>         }
>  }
> 
> -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
> +                                               struct i2c_msg *msg)
>  {
>         u32 addr, len, val;
> 
> @@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         writel(val, qup->base + QUP_OUT_FIFO_BASE);
>  }
> 
> +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
> +                                                                               *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_issue_xfer_v2(qup, msg);
> +       else
> +               qup_i2c_issue_read_v1(qup, msg);
> +}
> 
> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>  {
> -       u32 opflags;
>         u32 val = 0;
>         int idx;
> +       int len = msg->len + qup->rx_tag_len;

Is this intentional?

> 
> -       for (idx = 0; qup->pos < msg->len; idx++) {
> +       for (idx = 0; qup->pos < len; idx++) {
>                 if ((idx & 1) == 0) {
>                         /* Check that FIFO have data */
> -                       opflags = readl(qup->base + QUP_OPERATIONAL);
> -                       if (!(opflags & QUP_IN_NOT_EMPTY))
> +                       if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {

This should be part of the first patch.

> +                               dev_err(qup->dev, "timeout for fifo not empty");
>                                 break;
> -
> +                       }
>                         /* Reading 2 words at time */
>                         val = readl(qup->base + QUP_IN_FIFO_BASE);
> 
> @@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>         }
>  }
> 
> -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> +static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
> +                                       struct i2c_msg *msg)
> +{
> +       u32 val;
> +       int idx;
> +       int pos = 0;
> +       /* 2 extra bytes for read tags */
> +       int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
> +
> +       while (pos < total) {
> +               /* Check that FIFO have data */
> +               if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
> +                       dev_err(qup->dev, "timeout for fifo not empty");
> +                       break;

Error not propagated.

> +               }
> +               val = readl(qup->base + QUP_IN_FIFO_BASE);
> +
> +               for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
> +                       /* first 2 bytes are tag bytes */
> +                       if (pos < 2)
> +                               continue;
> +
> +                       if (pos >= total)
> +                               return;
> +
> +                       msg->buf[qup->pos++] = val & 0xff;
> +               }
> +       }
> +}
> +
> +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
> +                                                                       struct i2c_msg *msg)
> +{
> +       if (qup->use_v2_tags)
> +               qup_i2c_read_fifo_v2(qup, msg);
> +       else
> +               qup_i2c_read_fifo_v1(qup, msg);
> +}
> +
> +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> +                                                       int run, int last)
>  {
>         unsigned long left;
>         int ret;
> -
>         /*
>                 * The QUP block will issue a NACK and STOP on the bus when reaching
>                 * the end of the read, the length of the read is specified as one byte
> @@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> 
>         qup->msg = msg;
>         qup->pos  = 0;
> +       if (qup->use_v2_tags)
> +               qup_i2c_create_tag_v2(qup, msg, last);
> +       else
> +               qup->blk.blocks = 0;
> 
>         enable_irq(qup->irq);
> 
> -       qup_i2c_set_read_mode(qup, msg->len);
> +       qup_i2c_set_read_mode(qup, msg->len, run);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +       if (!run) {
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);

If !run, place controller in RUN state?

> +               if (ret)
> +                       goto err;
> +       }
> 
>         writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
> 
> -       ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
> -       if (ret)
> -               goto err;
> +       do {
> +               ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
> +               if (ret)
> +                       goto err;
> 
> -       qup_i2c_issue_read(qup, msg);
> +               qup_i2c_issue_read(qup, msg);
> 
> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> -       if (ret)
> -               goto err;
> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> +               if (ret)
> +                       goto err;
> 
> -       do {
>                 left = wait_for_completion_timeout(&qup->xfer, HZ);
>                 if (!left) {
>                         writel(1, qup->base + QUP_SW_RESET);
> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>                 }
> 
>                 qup_i2c_read_fifo(qup, msg);
> -       } while (qup->pos < msg->len);
> +               qup->blk.block_pos++;

This should not be incremented, unless we really have read this block.

> +       } while (qup->blk.block_pos < qup->blk.blocks);
> 
>  err:
>         disable_irq(qup->irq);
> @@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                         int num)
>  {
>         struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
> -       int ret, idx;
> +       int ret, idx, last;
> 
>         ret = pm_runtime_get_sync(qup->dev);
>         if (ret < 0)
> @@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                 goto out;
> 
>         /* Configure QUP as I2C mini core */
> -       writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
> +       if (qup->use_v2_tags) {
> +               writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
> +               writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
> +       } else {
> +               writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
> +       }
> 
>         for (idx = 0; idx < num; idx++) {
>                 if (msgs[idx].len == 0) {
> @@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                         goto out;
>                 }
> 
> +               reinit_completion(&qup->xfer);
> +
> +               last = (idx == (num - 1));
> +
>                 if (msgs[idx].flags & I2C_M_RD)
> -                       ret = qup_i2c_read_one(qup, &msgs[idx]);
> +                       ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
>                 else
> -                       ret = qup_i2c_write_one(qup, &msgs[idx]);
> +                       ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
> 
>                 if (ret)
>                         break;
> +       }
> 
> +       if (!ret)
>                 ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
> -               if (ret)
> -                       break;
> -       }
> 
>         if (ret == 0)
>                 ret = num;
>  out:
> 
> +       if (qup->use_v2_tags) {
> +               kfree(qup->tags);
> +               kfree(qup->blk.block_tag_len);
> +               kfree(qup->blk.block_data_len);
> +       }
> +
>         pm_runtime_mark_last_busy(qup->dev);
>         pm_runtime_put_autosuspend(qup->dev);
> 
> @@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
>         clk_prepare_enable(qup->pclk);
>  }
> 
> +static const struct of_device_id qup_i2c_dt_match[] = {
> +       { .compatible = "qcom,i2c-qup-v1.1.1"},
> +       { .compatible = "qcom,i2c-qup-v2.1.1"},
> +       { .compatible = "qcom,i2c-qup-v2.2.1"},

Space before closing brace, please.

I am starting to think that it will be more readable
if we just define qup_i2c_algo_v2 and use it, if 
controller is v2 and upwards?

Ivan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-14 15:16     ` Ivan T. Ivanov
  (?)
@ 2015-04-15  6:39         ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15  6:39 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, agross-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Ivan,


On 04/14/2015 08:46 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Sat, 2015-04-11 at 12:39 +0530, Sricharan R wrote:
>> From: Andy Gross <agross-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>>
>> 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.
>>
>
> But the read and write messages size QUP_READ_LIMIT?
>
   The READ_LIMIT is not true with the V2 tags. The controller can
   read/write multiple of 256 bytes sub-transfers to make transactions
   greater than > 256. Infact, i will have to remove the check for the
   READ_LIMIT in case of V2. I will add that.

>> 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 <agross-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> Signed-off-by: Sricharan R <sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> ---
>> [V3] Addressed comments from Andy Gross <agross-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>>       to coalesce each i2c_msg in i2c_msgs as a single transfer.
>>       Added macros to i2c_wait_ready function.
>>
>>   drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
>>   1 file changed, 337 insertions(+), 56 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>> index 9ccf3e8..16a8f69 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -24,6 +24,7 @@
>>   #include <linux/of.h>
>>   #include <linux/platform_device.h>
>>   #include <linux/pm_runtime.h>
>> +#include <linux/slab.h>
>>
>>   /* QUP Registers */
>>   #define QUP_CONFIG             0x000
>> @@ -42,6 +43,7 @@
>>   #define QUP_IN_FIFO_BASE       0x218
>>   #define QUP_I2C_CLK_CTL                0x400
>>   #define QUP_I2C_STATUS         0x404
>> +#define QUP_I2C_MASTER_GEN     0x408
>>
>>   /* QUP States and reset values */
>>   #define QUP_RESET_STATE                0
>> @@ -69,6 +71,8 @@
>>   #define QUP_CLOCK_AUTO_GATE    BIT(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)
>>
>> @@ -80,17 +84,30 @@
>>
>>   #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)
>>   #define QUP_INPUT_BLOCK_SIZE(x)        (((x) >> 5) & 0x03)
>>   #define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
>>
>> -/* QUP tags */
>> +/* QUP V1 tags */
>>   #define QUP_TAG_START          (1 << 8)
>>   #define QUP_TAG_DATA           (2 << 8)
>>   #define QUP_TAG_STOP           (3 << 8)
>>   #define QUP_TAG_REC            (4 << 8)
>>
>> +/* QUP v2 tags */
>> +#define QUP_TAG_V2_HS                  0xff
>> +#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
>> +
>> +/* frequency definitions for high speed and max speed */
>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>
> This is fast mode, if I am not mistaken.
>
  ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
  We use this macro to check if the desired freq is in HS range.
  The above comment can be changed though to make it clear.
>> +
>>   /* Status, Error flags */
>>   #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>   #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>> @@ -102,6 +119,15 @@
>>   #define RESET_BIT                      0x0
>>   #define ONE_BYTE                       0x1
>>
>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>
> Could you explain what is this for?
>
   This is a new feature in the V2 version of the controller,
   to support multiple i2c sub transfers without having
   a 'stop' bit in-between. Without this the i2c controller
   inserts a 'stop' on the bus when the WR/RD count registers
   reaches zero and are configured for the next transfer. So setting
   this bit when the controller is in 'RUN' state, avoids sending the
   'stop' during RUN state.
   I can add this comment in the patch.

>> +
>> +struct qup_i2c_block {
>> +       int     blocks;
>> +       u8      *block_tag_len;
>> +       int     *block_data_len;
>> +       int     block_pos;
>> +};
>> +
>>   struct qup_i2c_dev {
>>          struct device*dev;
>>          void __iomem*base;
>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>          int     in_fifo_sz;
>>          int     out_blk_sz;
>>          int     in_blk_sz;
>> -
>> +       struct  qup_i2c_blockblk;
>>          unsigned longone_byte_t;
>>
>> +       int     is_hs;
>> +       bool    use_v2_tags;
>> +
>> +       int     tx_tag_len;
>> +       int     rx_tag_len;
>> +       u8      *tags;
>> +       int     tags_pos;
>> +
>>          struct i2c_msg*msg;
>>          /* Current posion in user message buffer */
>>          int     pos;
>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>          }
>>   }
>
> Is this better tag related fields grouping?
>

> struct qup_i2c_tag_block {
>
>          u8      tag[2];
>          // int  tag_len; this is alway 2, or?
>          int     data_len; // this could be zero, right?
> };
>
There is a struct for qup_i2c_block which has tag and data len. Not sure 
what change you suggest above ? Also with V2 transfers tag len need
  not be 2. It can be more than that based on the data len.

>>
>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run)
>
> And 'run' stands for?
  'run' just says whether the controller is in 'RUN' or 'RESET' state.
   I can change it to is_run_st to make it clear.
>
>>   {
>> -       /* Number of entries to shift out, including the start */
>> -       int total = msg->len + 1;
>> +       /* Total Number of entries to shift out, including the tags */
>> +       int total;
>> +
>> +       if (qup->use_v2_tags) {
>> +               total = msg->len + qup->tx_tag_len;
>> +               if (run)
>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> What?
>
      This means, if the controller is in 'RUN' state, for
      reconfiguring the RD/WR counts this bit has to be set to avoid
      'stop' bits.

>> +       } else {
>> +               total = msg->len + 1; /* plus start tag */
>> +       }
>>
>>          if (total < qup->out_fifo_sz) {
>>                  /* FIFO mode */
>> @@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>>          u32 addr = msg->addr << 1;
>>          u32 qup_tag;
>> @@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg, int last)
>> +{
>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>> +       int len = 0, prev_len = 0;
>> +       int blocks = 0;
>> +       int rem;
>> +       int block_len = 0;
>> +       int data_len;
>> +
>> +       qup->blk.block_pos = 0;
>> +       qup->pos = 0;
>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>> +       rem = msg->len % QUP_READ_LIMIT;
>> +
>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>> +                                               qup->blk.blocks, GFP_KERNEL);
>
> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>
>
> Allocations could fail and memory is leaking here.
>
  ya correct, will change this. Freeing is done at the end of xfer
  function, but will have to check for allocation failure.

>> +
>> +       while (blocks < qup->blk.blocks) {
>> +               /* 0 is used to specify a READ_LIMIT of 256 bytes */
>> +               data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
>> +
>> +               /* Send START and ADDR bytes only for the first block */
>> +               if (!blocks) {
>> +                       qup->tags[len++] = QUP_TAG_V2_START;
>> +
>> +                       if (qup->is_hs) {
>> +                               qup->tags[len++] = QUP_TAG_V2_HS;
>> +                               qup->tags[len++] = QUP_TAG_V2_START;
>> +                       }
>> +
>> +                       qup->tags[len++] = addr & 0xff;
>> +                       if (msg->flags & I2C_M_TEN)
>> +                               qup->tags[len++] = addr >> 8;
>
> I have counted 5 bytes for first block?
>
    Yes 5 bytes for TEN bit addresses or HS mode. So i will have to add
    extra  bytes in the above allocation. Will change that. Thanks for
    pointing.
>> +               }
>> +
>> +               /* Send _STOP commands for the last block */
>> +               if ((blocks == (qup->blk.blocks - 1)) && last) {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
>> +               } else {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR;
>> +               }
>> +
>> +               qup->tags[len++] = data_len;
>> +               block_len = len - prev_len;
>> +               prev_len = len;
>> +               qup->blk.block_tag_len[blocks] = block_len;
>> +
>> +               if (!data_len)
>> +                       qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
>> +               else
>> +                       qup->blk.block_data_len[blocks] = data_len;
>> +
>> +               qup->tags_pos = 0;
>
> Every time?
>
  ok, infact unsed. Will remove it.
>> +               blocks++;
>
> Looks like 'for' cycle to me.
>
  sorry, not getting it ?
>> +       }
>> +
>> +       qup->tx_tag_len = len;
>> +
>> +       if (msg->flags & I2C_M_RD)
>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>> +       else
>> +               qup->rx_tag_len = 0;
>> +}
>> +
>> +static u32 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;
>> +
>> +       while (len > 0) {
>> +               if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo out full");
>> +                       break;
>
> Error not propagated?
>
   Ok, will change this and another place to return the err no correctly.
>> +               }
>> +
>> +               t = (len >= 4) ? 4 : len;
>> +
>> +               while (idx < t) {
>> +                       if (!i && (pos >= tlen)) {
>> +                               buf = dbuf;
>> +                               pos = 0;
>> +                               i = 1;
>> +                       }
>> +                       val |= buf[pos++] << (idx++ * 8);
>> +               }
>> +
>> +               writel(val, qup->base + QUP_OUT_FIFO_BASE);
>> +               idx  = 0;
>> +               val = 0;
>> +               len -= 4;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +{
>> +       u32 data_len = 0, tag_len;
>> +
>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>> +
>> +       if (!(msg->flags & I2C_M_RD))
>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>> +
>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>
> This assumes that writes are up to 256 bytes, and tags and data blocks
> are completely written to FIFO buffer, right?
>
  Yes, since we send/read data in blocks (256 bytes).
>> +}
>> +
>> +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> +                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_write_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                               int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          qup->msg = msg;
>>          qup->pos = 0;
>>
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>> +
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_write_mode(qup, msg);
>> +       qup_i2c_set_write_mode(qup, msg, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> To run away, or not?
>
   Means, if the controller is not in RUN state, put it in to 'RUN'
   state.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> @@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                          ret = -EIO;
>>                          goto err;
>>                  }
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>          /* Wait for the outstanding data in the fifo to drain */
>> -       ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
>> +       if (last)
>> +               ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
>> +                                               ONE_BYTE);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -375,8 +557,17 @@ err:
>>          return ret;
>>   }
>>
>> -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>> +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
>>   {
>> +       if (qup->use_v2_tags) {
>> +               len += qup->rx_tag_len;
>> +               if (run) {
>> +                       len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> Again? It looks like some kind of magic, to trick the controller
> that there are more bytes to transfer, or?
    This means, reconfiguring the _COUNTS when the controller is in
     'RUN' state to avoid having 'stop' bit on the bus.
>
>> +                       qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>> +               }
>> +               writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
>> +       }
>> +
>>          if (len < qup->in_fifo_sz) {
>>                  /* FIFO mode */
>>                  writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
>> @@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg)
>>   {
>>          u32 addr, len, val;
>>
>> @@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          writel(val, qup->base + QUP_OUT_FIFO_BASE);
>>   }
>>
>> +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
>> +                                                                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_read_v1(qup, msg);
>> +}
>>
>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>> -       u32 opflags;
>>          u32 val = 0;
>>          int idx;
>> +       int len = msg->len + qup->rx_tag_len;
>
> Is this intentional?
>
    Yes, since i changed the loop around qup_i2c_read_one to count for
    blocks. Ok, as you say i can change and keep if (use->v2_tags) checks
    in one place, set the variables accordingly to have better
    readability.

>>
>> -       for (idx = 0; qup->pos < msg->len; idx++) {
>> +       for (idx = 0; qup->pos < len; idx++) {
>>                  if ((idx & 1) == 0) {
>>                          /* Check that FIFO have data */
>> -                       opflags = readl(qup->base + QUP_OPERATIONAL);
>> -                       if (!(opflags & QUP_IN_NOT_EMPTY))
>> +                       if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>
> This should be part of the first patch.
    ok correct. Will move this below.
>
>> +                               dev_err(qup->dev, "timeout for fifo not empty");
>>                                  break;
>> -
>> +                       }
>>                          /* Reading 2 words at time */
>>                          val = readl(qup->base + QUP_IN_FIFO_BASE);
>>
>> @@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>> +                                       struct i2c_msg *msg)
>> +{
>> +       u32 val;
>> +       int idx;
>> +       int pos = 0;
>> +       /* 2 extra bytes for read tags */
>> +       int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
>> +
>> +       while (pos < total) {
>> +               /* Check that FIFO have data */
>> +               if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo not empty");
>> +                       break;
>
> Error not propagated.
>
  ok, will change this.
>> +               }
>> +               val = readl(qup->base + QUP_IN_FIFO_BASE);
>> +
>> +               for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
>> +                       /* first 2 bytes are tag bytes */
>> +                       if (pos < 2)
>> +                               continue;
>> +
>> +                       if (pos >= total)
>> +                               return;
>> +
>> +                       msg->buf[qup->pos++] = val & 0xff;
>> +               }
>> +       }
>> +}
>> +
>> +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
>> +                                                                       struct i2c_msg *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_read_fifo_v2(qup, msg);
>> +       else
>> +               qup_i2c_read_fifo_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> -
>>          /*
>>                  * The QUP block will issue a NACK and STOP on the bus when reaching
>>                  * the end of the read, the length of the read is specified as one byte
>> @@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>
>>          qup->msg = msg;
>>          qup->pos  = 0;
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>>
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_read_mode(qup, msg->len);
>> +       qup_i2c_set_read_mode(qup, msg->len, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> If !run, place controller in RUN state?
>
   Yes, correct.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> -       if (ret)
>> -               goto err;
>> +       do {
>> +               ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       qup_i2c_issue_read(qup, msg);
>> +               qup_i2c_issue_read(qup, msg);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       do {
>>                  left = wait_for_completion_timeout(&qup->xfer, HZ);
>>                  if (!left) {
>>                          writel(1, qup->base + QUP_SW_RESET);
>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                  }
>>
>>                  qup_i2c_read_fifo(qup, msg);
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>
> This should not be incremented, unless we really have read this block.
>
   We are reading it and only then incrementing it.

>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          int num)
>>   {
>>          struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
>> -       int ret, idx;
>> +       int ret, idx, last;
>>
>>          ret = pm_runtime_get_sync(qup->dev);
>>          if (ret < 0)
>> @@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                  goto out;
>>
>>          /* Configure QUP as I2C mini core */
>> -       writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       if (qup->use_v2_tags) {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
>> +               writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
>> +       } else {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       }
>>
>>          for (idx = 0; idx < num; idx++) {
>>                  if (msgs[idx].len == 0) {
>> @@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          goto out;
>>                  }
>>
>> +               reinit_completion(&qup->xfer);
>> +
>> +               last = (idx == (num - 1));
>> +
>>                  if (msgs[idx].flags & I2C_M_RD)
>> -                       ret = qup_i2c_read_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
>>                  else
>> -                       ret = qup_i2c_write_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
>>
>>                  if (ret)
>>                          break;
>> +       }
>>
>> +       if (!ret)
>>                  ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
>> -               if (ret)
>> -                       break;
>> -       }
>>
>>          if (ret == 0)
>>                  ret = num;
>>   out:
>>
>> +       if (qup->use_v2_tags) {
>> +               kfree(qup->tags);
>> +               kfree(qup->blk.block_tag_len);
>> +               kfree(qup->blk.block_data_len);
>> +       }
>> +
>>          pm_runtime_mark_last_busy(qup->dev);
>>          pm_runtime_put_autosuspend(qup->dev);
>>
>> @@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
>>          clk_prepare_enable(qup->pclk);
>>   }
>>
>> +static const struct of_device_id qup_i2c_dt_match[] = {
>> +       { .compatible = "qcom,i2c-qup-v1.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.2.1"},
>
> Space before closing brace, please.
>
  ok, will change.
> I am starting to think that it will be more readable
> if we just define qup_i2c_algo_v2 and use it, if
> controller is v2 and upwards?
>
  As i said will keep all the use_v2 tags check in one place
  to have better readability.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-15  6:39         ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15  6:39 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel

Hi Ivan,


On 04/14/2015 08:46 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Sat, 2015-04-11 at 12:39 +0530, Sricharan R wrote:
>> From: Andy Gross <agross@codeaurora.org>
>>
>> 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.
>>
>
> But the read and write messages size QUP_READ_LIMIT?
>
   The READ_LIMIT is not true with the V2 tags. The controller can
   read/write multiple of 256 bytes sub-transfers to make transactions
   greater than > 256. Infact, i will have to remove the check for the
   READ_LIMIT in case of V2. I will add that.

>> 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 <agross@codeaurora.org>
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> ---
>> [V3] Addressed comments from Andy Gross <agross@codeaurora.org>
>>       to coalesce each i2c_msg in i2c_msgs as a single transfer.
>>       Added macros to i2c_wait_ready function.
>>
>>   drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
>>   1 file changed, 337 insertions(+), 56 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>> index 9ccf3e8..16a8f69 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -24,6 +24,7 @@
>>   #include <linux/of.h>
>>   #include <linux/platform_device.h>
>>   #include <linux/pm_runtime.h>
>> +#include <linux/slab.h>
>>
>>   /* QUP Registers */
>>   #define QUP_CONFIG             0x000
>> @@ -42,6 +43,7 @@
>>   #define QUP_IN_FIFO_BASE       0x218
>>   #define QUP_I2C_CLK_CTL                0x400
>>   #define QUP_I2C_STATUS         0x404
>> +#define QUP_I2C_MASTER_GEN     0x408
>>
>>   /* QUP States and reset values */
>>   #define QUP_RESET_STATE                0
>> @@ -69,6 +71,8 @@
>>   #define QUP_CLOCK_AUTO_GATE    BIT(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)
>>
>> @@ -80,17 +84,30 @@
>>
>>   #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)
>>   #define QUP_INPUT_BLOCK_SIZE(x)        (((x) >> 5) & 0x03)
>>   #define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
>>
>> -/* QUP tags */
>> +/* QUP V1 tags */
>>   #define QUP_TAG_START          (1 << 8)
>>   #define QUP_TAG_DATA           (2 << 8)
>>   #define QUP_TAG_STOP           (3 << 8)
>>   #define QUP_TAG_REC            (4 << 8)
>>
>> +/* QUP v2 tags */
>> +#define QUP_TAG_V2_HS                  0xff
>> +#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
>> +
>> +/* frequency definitions for high speed and max speed */
>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>
> This is fast mode, if I am not mistaken.
>
  ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
  We use this macro to check if the desired freq is in HS range.
  The above comment can be changed though to make it clear.
>> +
>>   /* Status, Error flags */
>>   #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>   #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>> @@ -102,6 +119,15 @@
>>   #define RESET_BIT                      0x0
>>   #define ONE_BYTE                       0x1
>>
>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>
> Could you explain what is this for?
>
   This is a new feature in the V2 version of the controller,
   to support multiple i2c sub transfers without having
   a 'stop' bit in-between. Without this the i2c controller
   inserts a 'stop' on the bus when the WR/RD count registers
   reaches zero and are configured for the next transfer. So setting
   this bit when the controller is in 'RUN' state, avoids sending the
   'stop' during RUN state.
   I can add this comment in the patch.

>> +
>> +struct qup_i2c_block {
>> +       int     blocks;
>> +       u8      *block_tag_len;
>> +       int     *block_data_len;
>> +       int     block_pos;
>> +};
>> +
>>   struct qup_i2c_dev {
>>          struct device*dev;
>>          void __iomem*base;
>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>          int     in_fifo_sz;
>>          int     out_blk_sz;
>>          int     in_blk_sz;
>> -
>> +       struct  qup_i2c_blockblk;
>>          unsigned longone_byte_t;
>>
>> +       int     is_hs;
>> +       bool    use_v2_tags;
>> +
>> +       int     tx_tag_len;
>> +       int     rx_tag_len;
>> +       u8      *tags;
>> +       int     tags_pos;
>> +
>>          struct i2c_msg*msg;
>>          /* Current posion in user message buffer */
>>          int     pos;
>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>          }
>>   }
>
> Is this better tag related fields grouping?
>

> struct qup_i2c_tag_block {
>
>          u8      tag[2];
>          // int  tag_len; this is alway 2, or?
>          int     data_len; // this could be zero, right?
> };
>
There is a struct for qup_i2c_block which has tag and data len. Not sure 
what change you suggest above ? Also with V2 transfers tag len need
  not be 2. It can be more than that based on the data len.

>>
>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run)
>
> And 'run' stands for?
  'run' just says whether the controller is in 'RUN' or 'RESET' state.
   I can change it to is_run_st to make it clear.
>
>>   {
>> -       /* Number of entries to shift out, including the start */
>> -       int total = msg->len + 1;
>> +       /* Total Number of entries to shift out, including the tags */
>> +       int total;
>> +
>> +       if (qup->use_v2_tags) {
>> +               total = msg->len + qup->tx_tag_len;
>> +               if (run)
>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> What?
>
      This means, if the controller is in 'RUN' state, for
      reconfiguring the RD/WR counts this bit has to be set to avoid
      'stop' bits.

>> +       } else {
>> +               total = msg->len + 1; /* plus start tag */
>> +       }
>>
>>          if (total < qup->out_fifo_sz) {
>>                  /* FIFO mode */
>> @@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>>          u32 addr = msg->addr << 1;
>>          u32 qup_tag;
>> @@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg, int last)
>> +{
>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>> +       int len = 0, prev_len = 0;
>> +       int blocks = 0;
>> +       int rem;
>> +       int block_len = 0;
>> +       int data_len;
>> +
>> +       qup->blk.block_pos = 0;
>> +       qup->pos = 0;
>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>> +       rem = msg->len % QUP_READ_LIMIT;
>> +
>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>> +                                               qup->blk.blocks, GFP_KERNEL);
>
> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>
>
> Allocations could fail and memory is leaking here.
>
  ya correct, will change this. Freeing is done at the end of xfer
  function, but will have to check for allocation failure.

>> +
>> +       while (blocks < qup->blk.blocks) {
>> +               /* 0 is used to specify a READ_LIMIT of 256 bytes */
>> +               data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
>> +
>> +               /* Send START and ADDR bytes only for the first block */
>> +               if (!blocks) {
>> +                       qup->tags[len++] = QUP_TAG_V2_START;
>> +
>> +                       if (qup->is_hs) {
>> +                               qup->tags[len++] = QUP_TAG_V2_HS;
>> +                               qup->tags[len++] = QUP_TAG_V2_START;
>> +                       }
>> +
>> +                       qup->tags[len++] = addr & 0xff;
>> +                       if (msg->flags & I2C_M_TEN)
>> +                               qup->tags[len++] = addr >> 8;
>
> I have counted 5 bytes for first block?
>
    Yes 5 bytes for TEN bit addresses or HS mode. So i will have to add
    extra  bytes in the above allocation. Will change that. Thanks for
    pointing.
>> +               }
>> +
>> +               /* Send _STOP commands for the last block */
>> +               if ((blocks == (qup->blk.blocks - 1)) && last) {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
>> +               } else {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR;
>> +               }
>> +
>> +               qup->tags[len++] = data_len;
>> +               block_len = len - prev_len;
>> +               prev_len = len;
>> +               qup->blk.block_tag_len[blocks] = block_len;
>> +
>> +               if (!data_len)
>> +                       qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
>> +               else
>> +                       qup->blk.block_data_len[blocks] = data_len;
>> +
>> +               qup->tags_pos = 0;
>
> Every time?
>
  ok, infact unsed. Will remove it.
>> +               blocks++;
>
> Looks like 'for' cycle to me.
>
  sorry, not getting it ?
>> +       }
>> +
>> +       qup->tx_tag_len = len;
>> +
>> +       if (msg->flags & I2C_M_RD)
>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>> +       else
>> +               qup->rx_tag_len = 0;
>> +}
>> +
>> +static u32 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;
>> +
>> +       while (len > 0) {
>> +               if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo out full");
>> +                       break;
>
> Error not propagated?
>
   Ok, will change this and another place to return the err no correctly.
>> +               }
>> +
>> +               t = (len >= 4) ? 4 : len;
>> +
>> +               while (idx < t) {
>> +                       if (!i && (pos >= tlen)) {
>> +                               buf = dbuf;
>> +                               pos = 0;
>> +                               i = 1;
>> +                       }
>> +                       val |= buf[pos++] << (idx++ * 8);
>> +               }
>> +
>> +               writel(val, qup->base + QUP_OUT_FIFO_BASE);
>> +               idx  = 0;
>> +               val = 0;
>> +               len -= 4;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +{
>> +       u32 data_len = 0, tag_len;
>> +
>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>> +
>> +       if (!(msg->flags & I2C_M_RD))
>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>> +
>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>
> This assumes that writes are up to 256 bytes, and tags and data blocks
> are completely written to FIFO buffer, right?
>
  Yes, since we send/read data in blocks (256 bytes).
>> +}
>> +
>> +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> +                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_write_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                               int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          qup->msg = msg;
>>          qup->pos = 0;
>>
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>> +
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_write_mode(qup, msg);
>> +       qup_i2c_set_write_mode(qup, msg, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> To run away, or not?
>
   Means, if the controller is not in RUN state, put it in to 'RUN'
   state.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> @@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                          ret = -EIO;
>>                          goto err;
>>                  }
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>          /* Wait for the outstanding data in the fifo to drain */
>> -       ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
>> +       if (last)
>> +               ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
>> +                                               ONE_BYTE);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -375,8 +557,17 @@ err:
>>          return ret;
>>   }
>>
>> -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>> +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
>>   {
>> +       if (qup->use_v2_tags) {
>> +               len += qup->rx_tag_len;
>> +               if (run) {
>> +                       len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> Again? It looks like some kind of magic, to trick the controller
> that there are more bytes to transfer, or?
    This means, reconfiguring the _COUNTS when the controller is in
     'RUN' state to avoid having 'stop' bit on the bus.
>
>> +                       qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>> +               }
>> +               writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
>> +       }
>> +
>>          if (len < qup->in_fifo_sz) {
>>                  /* FIFO mode */
>>                  writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
>> @@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg)
>>   {
>>          u32 addr, len, val;
>>
>> @@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          writel(val, qup->base + QUP_OUT_FIFO_BASE);
>>   }
>>
>> +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
>> +                                                                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_read_v1(qup, msg);
>> +}
>>
>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>> -       u32 opflags;
>>          u32 val = 0;
>>          int idx;
>> +       int len = msg->len + qup->rx_tag_len;
>
> Is this intentional?
>
    Yes, since i changed the loop around qup_i2c_read_one to count for
    blocks. Ok, as you say i can change and keep if (use->v2_tags) checks
    in one place, set the variables accordingly to have better
    readability.

>>
>> -       for (idx = 0; qup->pos < msg->len; idx++) {
>> +       for (idx = 0; qup->pos < len; idx++) {
>>                  if ((idx & 1) == 0) {
>>                          /* Check that FIFO have data */
>> -                       opflags = readl(qup->base + QUP_OPERATIONAL);
>> -                       if (!(opflags & QUP_IN_NOT_EMPTY))
>> +                       if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>
> This should be part of the first patch.
    ok correct. Will move this below.
>
>> +                               dev_err(qup->dev, "timeout for fifo not empty");
>>                                  break;
>> -
>> +                       }
>>                          /* Reading 2 words at time */
>>                          val = readl(qup->base + QUP_IN_FIFO_BASE);
>>
>> @@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>> +                                       struct i2c_msg *msg)
>> +{
>> +       u32 val;
>> +       int idx;
>> +       int pos = 0;
>> +       /* 2 extra bytes for read tags */
>> +       int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
>> +
>> +       while (pos < total) {
>> +               /* Check that FIFO have data */
>> +               if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo not empty");
>> +                       break;
>
> Error not propagated.
>
  ok, will change this.
>> +               }
>> +               val = readl(qup->base + QUP_IN_FIFO_BASE);
>> +
>> +               for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
>> +                       /* first 2 bytes are tag bytes */
>> +                       if (pos < 2)
>> +                               continue;
>> +
>> +                       if (pos >= total)
>> +                               return;
>> +
>> +                       msg->buf[qup->pos++] = val & 0xff;
>> +               }
>> +       }
>> +}
>> +
>> +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
>> +                                                                       struct i2c_msg *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_read_fifo_v2(qup, msg);
>> +       else
>> +               qup_i2c_read_fifo_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> -
>>          /*
>>                  * The QUP block will issue a NACK and STOP on the bus when reaching
>>                  * the end of the read, the length of the read is specified as one byte
>> @@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>
>>          qup->msg = msg;
>>          qup->pos  = 0;
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>>
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_read_mode(qup, msg->len);
>> +       qup_i2c_set_read_mode(qup, msg->len, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> If !run, place controller in RUN state?
>
   Yes, correct.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> -       if (ret)
>> -               goto err;
>> +       do {
>> +               ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       qup_i2c_issue_read(qup, msg);
>> +               qup_i2c_issue_read(qup, msg);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       do {
>>                  left = wait_for_completion_timeout(&qup->xfer, HZ);
>>                  if (!left) {
>>                          writel(1, qup->base + QUP_SW_RESET);
>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                  }
>>
>>                  qup_i2c_read_fifo(qup, msg);
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>
> This should not be incremented, unless we really have read this block.
>
   We are reading it and only then incrementing it.

>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          int num)
>>   {
>>          struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
>> -       int ret, idx;
>> +       int ret, idx, last;
>>
>>          ret = pm_runtime_get_sync(qup->dev);
>>          if (ret < 0)
>> @@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                  goto out;
>>
>>          /* Configure QUP as I2C mini core */
>> -       writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       if (qup->use_v2_tags) {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
>> +               writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
>> +       } else {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       }
>>
>>          for (idx = 0; idx < num; idx++) {
>>                  if (msgs[idx].len == 0) {
>> @@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          goto out;
>>                  }
>>
>> +               reinit_completion(&qup->xfer);
>> +
>> +               last = (idx == (num - 1));
>> +
>>                  if (msgs[idx].flags & I2C_M_RD)
>> -                       ret = qup_i2c_read_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
>>                  else
>> -                       ret = qup_i2c_write_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
>>
>>                  if (ret)
>>                          break;
>> +       }
>>
>> +       if (!ret)
>>                  ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
>> -               if (ret)
>> -                       break;
>> -       }
>>
>>          if (ret == 0)
>>                  ret = num;
>>   out:
>>
>> +       if (qup->use_v2_tags) {
>> +               kfree(qup->tags);
>> +               kfree(qup->blk.block_tag_len);
>> +               kfree(qup->blk.block_data_len);
>> +       }
>> +
>>          pm_runtime_mark_last_busy(qup->dev);
>>          pm_runtime_put_autosuspend(qup->dev);
>>
>> @@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
>>          clk_prepare_enable(qup->pclk);
>>   }
>>
>> +static const struct of_device_id qup_i2c_dt_match[] = {
>> +       { .compatible = "qcom,i2c-qup-v1.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.2.1"},
>
> Space before closing brace, please.
>
  ok, will change.
> I am starting to think that it will be more readable
> if we just define qup_i2c_algo_v2 and use it, if
> controller is v2 and upwards?
>
  As i said will keep all the use_v2 tags check in one place
  to have better readability.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-15  6:39         ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15  6:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ivan,


On 04/14/2015 08:46 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Sat, 2015-04-11 at 12:39 +0530, Sricharan R wrote:
>> From: Andy Gross <agross@codeaurora.org>
>>
>> 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.
>>
>
> But the read and write messages size QUP_READ_LIMIT?
>
   The READ_LIMIT is not true with the V2 tags. The controller can
   read/write multiple of 256 bytes sub-transfers to make transactions
   greater than > 256. Infact, i will have to remove the check for the
   READ_LIMIT in case of V2. I will add that.

>> 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 <agross@codeaurora.org>
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> ---
>> [V3] Addressed comments from Andy Gross <agross@codeaurora.org>
>>       to coalesce each i2c_msg in i2c_msgs as a single transfer.
>>       Added macros to i2c_wait_ready function.
>>
>>   drivers/i2c/busses/i2c-qup.c | 393 +++++++++++++++++++++++++++++++++++++------
>>   1 file changed, 337 insertions(+), 56 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>> index 9ccf3e8..16a8f69 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -24,6 +24,7 @@
>>   #include <linux/of.h>
>>   #include <linux/platform_device.h>
>>   #include <linux/pm_runtime.h>
>> +#include <linux/slab.h>
>>
>>   /* QUP Registers */
>>   #define QUP_CONFIG             0x000
>> @@ -42,6 +43,7 @@
>>   #define QUP_IN_FIFO_BASE       0x218
>>   #define QUP_I2C_CLK_CTL                0x400
>>   #define QUP_I2C_STATUS         0x404
>> +#define QUP_I2C_MASTER_GEN     0x408
>>
>>   /* QUP States and reset values */
>>   #define QUP_RESET_STATE                0
>> @@ -69,6 +71,8 @@
>>   #define QUP_CLOCK_AUTO_GATE    BIT(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)
>>
>> @@ -80,17 +84,30 @@
>>
>>   #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)
>>   #define QUP_INPUT_BLOCK_SIZE(x)        (((x) >> 5) & 0x03)
>>   #define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
>>
>> -/* QUP tags */
>> +/* QUP V1 tags */
>>   #define QUP_TAG_START          (1 << 8)
>>   #define QUP_TAG_DATA           (2 << 8)
>>   #define QUP_TAG_STOP           (3 << 8)
>>   #define QUP_TAG_REC            (4 << 8)
>>
>> +/* QUP v2 tags */
>> +#define QUP_TAG_V2_HS                  0xff
>> +#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
>> +
>> +/* frequency definitions for high speed and max speed */
>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>
> This is fast mode, if I am not mistaken.
>
  ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
  We use this macro to check if the desired freq is in HS range.
  The above comment can be changed though to make it clear.
>> +
>>   /* Status, Error flags */
>>   #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>   #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>> @@ -102,6 +119,15 @@
>>   #define RESET_BIT                      0x0
>>   #define ONE_BYTE                       0x1
>>
>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>
> Could you explain what is this for?
>
   This is a new feature in the V2 version of the controller,
   to support multiple i2c sub transfers without having
   a 'stop' bit in-between. Without this the i2c controller
   inserts a 'stop' on the bus when the WR/RD count registers
   reaches zero and are configured for the next transfer. So setting
   this bit when the controller is in 'RUN' state, avoids sending the
   'stop' during RUN state.
   I can add this comment in the patch.

>> +
>> +struct qup_i2c_block {
>> +       int     blocks;
>> +       u8      *block_tag_len;
>> +       int     *block_data_len;
>> +       int     block_pos;
>> +};
>> +
>>   struct qup_i2c_dev {
>>          struct device*dev;
>>          void __iomem*base;
>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>          int     in_fifo_sz;
>>          int     out_blk_sz;
>>          int     in_blk_sz;
>> -
>> +       struct  qup_i2c_blockblk;
>>          unsigned longone_byte_t;
>>
>> +       int     is_hs;
>> +       bool    use_v2_tags;
>> +
>> +       int     tx_tag_len;
>> +       int     rx_tag_len;
>> +       u8      *tags;
>> +       int     tags_pos;
>> +
>>          struct i2c_msg*msg;
>>          /* Current posion in user message buffer */
>>          int     pos;
>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>          }
>>   }
>
> Is this better tag related fields grouping?
>

> struct qup_i2c_tag_block {
>
>          u8      tag[2];
>          // int  tag_len; this is alway 2, or?
>          int     data_len; // this could be zero, right?
> };
>
There is a struct for qup_i2c_block which has tag and data len. Not sure 
what change you suggest above ? Also with V2 transfers tag len need
  not be 2. It can be more than that based on the data len.

>>
>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run)
>
> And 'run' stands for?
  'run' just says whether the controller is in 'RUN' or 'RESET' state.
   I can change it to is_run_st to make it clear.
>
>>   {
>> -       /* Number of entries to shift out, including the start */
>> -       int total = msg->len + 1;
>> +       /* Total Number of entries to shift out, including the tags */
>> +       int total;
>> +
>> +       if (qup->use_v2_tags) {
>> +               total = msg->len + qup->tx_tag_len;
>> +               if (run)
>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> What?
>
      This means, if the controller is in 'RUN' state, for
      reconfiguring the RD/WR counts this bit has to be set to avoid
      'stop' bits.

>> +       } else {
>> +               total = msg->len + 1; /* plus start tag */
>> +       }
>>
>>          if (total < qup->out_fifo_sz) {
>>                  /* FIFO mode */
>> @@ -280,7 +323,7 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_write_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>>          u32 addr = msg->addr << 1;
>>          u32 qup_tag;
>> @@ -321,7 +364,136 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg, int last)
>> +{
>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>> +       int len = 0, prev_len = 0;
>> +       int blocks = 0;
>> +       int rem;
>> +       int block_len = 0;
>> +       int data_len;
>> +
>> +       qup->blk.block_pos = 0;
>> +       qup->pos = 0;
>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>> +       rem = msg->len % QUP_READ_LIMIT;
>> +
>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>> +                                               qup->blk.blocks, GFP_KERNEL);
>
> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>
>
> Allocations could fail and memory is leaking here.
>
  ya correct, will change this. Freeing is done at the end of xfer
  function, but will have to check for allocation failure.

>> +
>> +       while (blocks < qup->blk.blocks) {
>> +               /* 0 is used to specify a READ_LIMIT of 256 bytes */
>> +               data_len = (blocks < (qup->blk.blocks - 1)) ? 0 : rem;
>> +
>> +               /* Send START and ADDR bytes only for the first block */
>> +               if (!blocks) {
>> +                       qup->tags[len++] = QUP_TAG_V2_START;
>> +
>> +                       if (qup->is_hs) {
>> +                               qup->tags[len++] = QUP_TAG_V2_HS;
>> +                               qup->tags[len++] = QUP_TAG_V2_START;
>> +                       }
>> +
>> +                       qup->tags[len++] = addr & 0xff;
>> +                       if (msg->flags & I2C_M_TEN)
>> +                               qup->tags[len++] = addr >> 8;
>
> I have counted 5 bytes for first block?
>
    Yes 5 bytes for TEN bit addresses or HS mode. So i will have to add
    extra  bytes in the above allocation. Will change that. Thanks for
    pointing.
>> +               }
>> +
>> +               /* Send _STOP commands for the last block */
>> +               if ((blocks == (qup->blk.blocks - 1)) && last) {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR_STOP;
>> +               } else {
>> +                       if (msg->flags & I2C_M_RD)
>> +                               qup->tags[len++] = QUP_TAG_V2_DATARD;
>> +                       else
>> +                               qup->tags[len++] = QUP_TAG_V2_DATAWR;
>> +               }
>> +
>> +               qup->tags[len++] = data_len;
>> +               block_len = len - prev_len;
>> +               prev_len = len;
>> +               qup->blk.block_tag_len[blocks] = block_len;
>> +
>> +               if (!data_len)
>> +                       qup->blk.block_data_len[blocks] = QUP_READ_LIMIT;
>> +               else
>> +                       qup->blk.block_data_len[blocks] = data_len;
>> +
>> +               qup->tags_pos = 0;
>
> Every time?
>
  ok, infact unsed. Will remove it.
>> +               blocks++;
>
> Looks like 'for' cycle to me.
>
  sorry, not getting it ?
>> +       }
>> +
>> +       qup->tx_tag_len = len;
>> +
>> +       if (msg->flags & I2C_M_RD)
>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>> +       else
>> +               qup->rx_tag_len = 0;
>> +}
>> +
>> +static u32 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;
>> +
>> +       while (len > 0) {
>> +               if (qup_i2c_wait_ready(qup, QUP_OUT_FULL, 0, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo out full");
>> +                       break;
>
> Error not propagated?
>
   Ok, will change this and another place to return the err no correctly.
>> +               }
>> +
>> +               t = (len >= 4) ? 4 : len;
>> +
>> +               while (idx < t) {
>> +                       if (!i && (pos >= tlen)) {
>> +                               buf = dbuf;
>> +                               pos = 0;
>> +                               i = 1;
>> +                       }
>> +                       val |= buf[pos++] << (idx++ * 8);
>> +               }
>> +
>> +               writel(val, qup->base + QUP_OUT_FIFO_BASE);
>> +               idx  = 0;
>> +               val = 0;
>> +               len -= 4;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +{
>> +       u32 data_len = 0, tag_len;
>> +
>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>> +
>> +       if (!(msg->flags & I2C_M_RD))
>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>> +
>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>
> This assumes that writes are up to 256 bytes, and tags and data blocks
> are completely written to FIFO buffer, right?
>
  Yes, since we send/read data in blocks (256 bytes).
>> +}
>> +
>> +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg
>> +                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_write_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                               int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          qup->msg = msg;
>>          qup->pos = 0;
>>
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>> +
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_write_mode(qup, msg);
>> +       qup_i2c_set_write_mode(qup, msg, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> To run away, or not?
>
   Means, if the controller is not in RUN state, put it in to 'RUN'
   state.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> @@ -363,10 +542,13 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                          ret = -EIO;
>>                          goto err;
>>                  }
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>          /* Wait for the outstanding data in the fifo to drain */
>> -       ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
>> +       if (last)
>> +               ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT,
>> +                                               ONE_BYTE);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -375,8 +557,17 @@ err:
>>          return ret;
>>   }
>>
>> -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>> +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len, int run)
>>   {
>> +       if (qup->use_v2_tags) {
>> +               len += qup->rx_tag_len;
>> +               if (run) {
>> +                       len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>
> Again? It looks like some kind of magic, to trick the controller
> that there are more bytes to transfer, or?
    This means, reconfiguring the _COUNTS when the controller is in
     'RUN' state to avoid having 'stop' bit on the bus.
>
>> +                       qup->tx_tag_len |= QUP_I2C_MX_CONFIG_DURING_RUN;
>> +               }
>> +               writel(qup->tx_tag_len, qup->base + QUP_MX_WRITE_CNT);
>> +       }
>> +
>>          if (len < qup->in_fifo_sz) {
>>                  /* FIFO mode */
>>                  writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
>> @@ -389,7 +580,8 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len)
>>          }
>>   }
>>
>> -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_issue_read_v1(struct qup_i2c_dev *qup,
>> +                                               struct i2c_msg *msg)
>>   {
>>          u32 addr, len, val;
>>
>> @@ -402,20 +594,28 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          writel(val, qup->base + QUP_OUT_FIFO_BASE);
>>   }
>>
>> +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg
>> +                                                                               *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_issue_xfer_v2(qup, msg);
>> +       else
>> +               qup_i2c_issue_read_v1(qup, msg);
>> +}
>>
>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>   {
>> -       u32 opflags;
>>          u32 val = 0;
>>          int idx;
>> +       int len = msg->len + qup->rx_tag_len;
>
> Is this intentional?
>
    Yes, since i changed the loop around qup_i2c_read_one to count for
    blocks. Ok, as you say i can change and keep if (use->v2_tags) checks
    in one place, set the variables accordingly to have better
    readability.

>>
>> -       for (idx = 0; qup->pos < msg->len; idx++) {
>> +       for (idx = 0; qup->pos < len; idx++) {
>>                  if ((idx & 1) == 0) {
>>                          /* Check that FIFO have data */
>> -                       opflags = readl(qup->base + QUP_OPERATIONAL);
>> -                       if (!(opflags & QUP_IN_NOT_EMPTY))
>> +                       if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>
> This should be part of the first patch.
    ok correct. Will move this below.
>
>> +                               dev_err(qup->dev, "timeout for fifo not empty");
>>                                  break;
>> -
>> +                       }
>>                          /* Reading 2 words at time */
>>                          val = readl(qup->base + QUP_IN_FIFO_BASE);
>>
>> @@ -426,11 +626,50 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>          }
>>   }
>>
>> -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>> +static void qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>> +                                       struct i2c_msg *msg)
>> +{
>> +       u32 val;
>> +       int idx;
>> +       int pos = 0;
>> +       /* 2 extra bytes for read tags */
>> +       int total = qup->blk.block_data_len[qup->blk.block_pos] + 2;
>> +
>> +       while (pos < total) {
>> +               /* Check that FIFO have data */
>> +               if (qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, 1, 4)) {
>> +                       dev_err(qup->dev, "timeout for fifo not empty");
>> +                       break;
>
> Error not propagated.
>
  ok, will change this.
>> +               }
>> +               val = readl(qup->base + QUP_IN_FIFO_BASE);
>> +
>> +               for (idx = 0; idx < 4; idx++, val >>= 8, pos++) {
>> +                       /* first 2 bytes are tag bytes */
>> +                       if (pos < 2)
>> +                               continue;
>> +
>> +                       if (pos >= total)
>> +                               return;
>> +
>> +                       msg->buf[qup->pos++] = val & 0xff;
>> +               }
>> +       }
>> +}
>> +
>> +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup,
>> +                                                                       struct i2c_msg *msg)
>> +{
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_read_fifo_v2(qup, msg);
>> +       else
>> +               qup_i2c_read_fifo_v1(qup, msg);
>> +}
>> +
>> +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>> +                                                       int run, int last)
>>   {
>>          unsigned long left;
>>          int ret;
>> -
>>          /*
>>                  * The QUP block will issue a NACK and STOP on the bus when reaching
>>                  * the end of the read, the length of the read is specified as one byte
>> @@ -444,28 +683,34 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>
>>          qup->msg = msg;
>>          qup->pos  = 0;
>> +       if (qup->use_v2_tags)
>> +               qup_i2c_create_tag_v2(qup, msg, last);
>> +       else
>> +               qup->blk.blocks = 0;
>>
>>          enable_irq(qup->irq);
>>
>> -       qup_i2c_set_read_mode(qup, msg->len);
>> +       qup_i2c_set_read_mode(qup, msg->len, run);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +       if (!run) {
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>
> If !run, place controller in RUN state?
>
   Yes, correct.
>> +               if (ret)
>> +                       goto err;
>> +       }
>>
>>          writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> -       if (ret)
>> -               goto err;
>> +       do {
>> +               ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       qup_i2c_issue_read(qup, msg);
>> +               qup_i2c_issue_read(qup, msg);
>>
>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> -       if (ret)
>> -               goto err;
>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>> +               if (ret)
>> +                       goto err;
>>
>> -       do {
>>                  left = wait_for_completion_timeout(&qup->xfer, HZ);
>>                  if (!left) {
>>                          writel(1, qup->base + QUP_SW_RESET);
>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                  }
>>
>>                  qup_i2c_read_fifo(qup, msg);
>> -       } while (qup->pos < msg->len);
>> +               qup->blk.block_pos++;
>
> This should not be incremented, unless we really have read this block.
>
   We are reading it and only then incrementing it.

>> +       } while (qup->blk.block_pos < qup->blk.blocks);
>>
>>   err:
>>          disable_irq(qup->irq);
>> @@ -495,7 +741,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          int num)
>>   {
>>          struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
>> -       int ret, idx;
>> +       int ret, idx, last;
>>
>>          ret = pm_runtime_get_sync(qup->dev);
>>          if (ret < 0)
>> @@ -507,7 +753,12 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                  goto out;
>>
>>          /* Configure QUP as I2C mini core */
>> -       writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       if (qup->use_v2_tags) {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
>> +               writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
>> +       } else {
>> +               writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
>> +       }
>>
>>          for (idx = 0; idx < num; idx++) {
>>                  if (msgs[idx].len == 0) {
>> @@ -520,23 +771,32 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          goto out;
>>                  }
>>
>> +               reinit_completion(&qup->xfer);
>> +
>> +               last = (idx == (num - 1));
>> +
>>                  if (msgs[idx].flags & I2C_M_RD)
>> -                       ret = qup_i2c_read_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_read_one(qup, &msgs[idx], idx, last);
>>                  else
>> -                       ret = qup_i2c_write_one(qup, &msgs[idx]);
>> +                       ret = qup_i2c_write_one(qup, &msgs[idx], idx, last);
>>
>>                  if (ret)
>>                          break;
>> +       }
>>
>> +       if (!ret)
>>                  ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
>> -               if (ret)
>> -                       break;
>> -       }
>>
>>          if (ret == 0)
>>                  ret = num;
>>   out:
>>
>> +       if (qup->use_v2_tags) {
>> +               kfree(qup->tags);
>> +               kfree(qup->blk.block_tag_len);
>> +               kfree(qup->blk.block_data_len);
>> +       }
>> +
>>          pm_runtime_mark_last_busy(qup->dev);
>>          pm_runtime_put_autosuspend(qup->dev);
>>
>> @@ -559,6 +819,14 @@ static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
>>          clk_prepare_enable(qup->pclk);
>>   }
>>
>> +static const struct of_device_id qup_i2c_dt_match[] = {
>> +       { .compatible = "qcom,i2c-qup-v1.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.1.1"},
>> +       { .compatible = "qcom,i2c-qup-v2.2.1"},
>
> Space before closing brace, please.
>
  ok, will change.
> I am starting to think that it will be more readable
> if we just define qup_i2c_algo_v2 and use it, if
> controller is v2 and upwards?
>
  As i said will keep all the use_v2 tags check in one place
  to have better readability.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-15  6:39         ` Sricharan R
@ 2015-04-15  8:49           ` Ivan T. Ivanov
  -1 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-15  8:49 UTC (permalink / raw)
  To: Sricharan R
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel


Hi Sricharan,

On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:

> > > +/* frequency definitions for high speed and max speed */
> > > +#define I2C_QUP_CLK_FAST_FREQ          1000000
> > 
> > This is fast mode, if I am not mistaken.
> > 
>   ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>   We use this macro to check if the desired freq is in HS range.
>   The above comment can be changed though to make it clear.

My point was that this is neither high nor max speed.

> > > +
> > >   /* Status, Error flags */
> > >   #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
> > >   #define I2C_STATUS_BUS_ACTIVE          BIT(8)
> > > @@ -102,6 +119,15 @@
> > >   #define RESET_BIT                      0x0
> > >   #define ONE_BYTE                       0x1
> > > 
> > > +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
> > 
> > Could you explain what is this for?
> > 
>    This is a new feature in the V2 version of the controller,
>    to support multiple i2c sub transfers without having
>    a 'stop' bit in-between. Without this the i2c controller
>    inserts a 'stop' on the bus when the WR/RD count registers
>    reaches zero and are configured for the next transfer. So setting
>    this bit when the controller is in 'RUN' state, avoids sending the
>    'stop' during RUN state.
>    I can add this comment in the patch.

And how v2 of this patch was worked if you introduce this bit now?
Bit is also not used by downstream driver, AFICS?

> 
> > > +
> > > +struct qup_i2c_block {
> > > +       int     blocks;

count

> > > +       u8      *block_tag_len;

just tag_len, 

> > > +       int     *block_data_len;

just data_len,

> > > +       int     block_pos;

just pos?

> > > +};
> > > +
> > >   struct qup_i2c_dev {
> > >          struct device*dev;
> > >          void __iomem*base;
> > > @@ -115,9 +141,17 @@ struct qup_i2c_dev {
> > >          int     in_fifo_sz;
> > >          int     out_blk_sz;
> > >          int     in_blk_sz;
> > > -
> > > +       struct  qup_i2c_blockblk;
> > >          unsigned longone_byte_t;
> > > 
> > > +       int     is_hs;
> > > +       bool    use_v2_tags;
> > > +
> > > +       int     tx_tag_len;
> > > +       int     rx_tag_len;
> > > +       u8      *tags;
> > > +       int     tags_pos;
> > > +
> > >          struct i2c_msg*msg;
> > >          /* Current posion in user message buffer */
> > >          int     pos;
> > > @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
> > >          }
> > >   }
> > 
> > Is this better tag related fields grouping?
> > 
> 
> > struct qup_i2c_tag_block {
> > 
> >          u8      tag[2];
> >          // int  tag_len; this is alway 2, or?
> >          int     data_len; // this could be zero, right?
> > };
> > 
> There is a struct for qup_i2c_block which has tag and data len. Not sure
> what change you suggest above ? Also with V2 transfers tag len need
>   not be 2. It can be more than that based on the data len.

The point is that: I will like to see better grouping of
related variables. Now they are spread all over. Would it
be possible to also take care for tx_tag_len, rx_tag_len, 
tags, tags_pos.

> 
> > > -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > +                                                       int run)
> > 
> > And 'run' stands for?
>   'run' just says whether the controller is in 'RUN' or 'RESET' state.
>    I can change it to is_run_st to make it clear.
> > >   {
> > > -       /* Number of entries to shift out, including the start */
> > > -       int total = msg->len + 1;
> > > +       /* Total Number of entries to shift out, including the tags */
> > > +       int total;
> > > +
> > > +       if (qup->use_v2_tags) {
> > > +               total = msg->len + qup->tx_tag_len;
> > > +               if (run)
> > > +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
> > 
> > What?
> > 
>       This means, if the controller is in 'RUN' state, for
>       reconfiguring the RD/WR counts this bit has to be set to avoid
>       'stop' bits.

I don't buy it, sorry. Problem with v1 of the tags is that controller
can not read more than 256 bytes without automatically generate STOP
at the end, because transfer length specified with QUP_TAG_REC tag
is 8 bits wide. There is no limitation for writes with v1 tags,
because controller is explicitly instructed when to send out STOP.

For v2 of the tags, writes behaves more or less the same, and the
good news are that there is new read tag QUP_TAG_V2_DATARD, which 
did't generate STOP when specified amount of data is read, still
up to 256 bytes in chunk. Read transfers with size more than 256
could be formed in following way:

V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.

> 
> > > 
> > > -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
> > > +                                               struct i2c_msg *msg, int last)
> > > +{
> > > +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
> > > +       int len = 0, prev_len = 0;
> > > +       int blocks = 0;
> > > +       int rem;
> > > +       int block_len = 0;
> > > +       int data_len;
> > > +
> > > +       qup->blk.block_pos = 0;
> > > +       qup->pos = 0;
> > > +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
> > > +       rem = msg->len % QUP_READ_LIMIT;
> > > +
> > > +       /* 2 tag bytes for each block + 2 extra bytes for first block */
> > > +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
> > > +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
> > > +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
> > > +                                               qup->blk.blocks, GFP_KERNEL);
> > 
> > Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
> > 
> > 
> > Allocations could fail and memory is leaking here.
> > 
>   ya correct, will change this. Freeing is done at the end of xfer
>   function, but will have to check for allocation failure.

Do you see how memory leak here? 

> 
> > > +
> > > +       while (blocks < qup->blk.blocks) {
> > > 
> > > +               blocks++;
> > 
> > Looks like 'for' cycle to me.
> > 
>   sorry, not getting it ?

This 'while' loop is old plain 'for'.

> > > +       }
> > > +
> > > +       qup->tx_tag_len = len;
> > > +
> > > +       if (msg->flags & I2C_M_RD)
> > > +               qup->rx_tag_len = (qup->blk.blocks * 2);

This will need some explanation.


> > > +
> > > +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +{
> > > +       u32 data_len = 0, tag_len;
> > > +
> > > +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> > > +
> > > +       if (!(msg->flags & I2C_M_RD))
> > > +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> > > +
> > > +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
> > 
> > This assumes that writes are up to 256 bytes, and tags and data blocks
> > are completely written to FIFO buffer, right?
> > 
>   Yes, since we send/read data in blocks (256 bytes).

How deep is the FIFO? Is it guaranteed that "the whole" write 
or read data, including tags will fit in.

> > > 
> > > +
> > > +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > +                                                               int run, int last)
> > >   {
> > >          unsigned long left;
> > >          int ret;
> > > @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >          qup->msg = msg;
> > >          qup->pos = 0;
> > > 
> > > +       if (qup->use_v2_tags)
> > > +               qup_i2c_create_tag_v2(qup, msg, last);
> > > +       else
> > > +               qup->blk.blocks = 0;
> > > +
> > >          enable_irq(qup->irq);
> > > 
> > > -       qup_i2c_set_write_mode(qup, msg);
> > > +       qup_i2c_set_write_mode(qup, msg, run);
> > > 
> > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > -       if (ret)
> > > -               goto err;
> > > +       if (!run) {
> > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > 
> > To run away, or not?
> > 
>    Means, if the controller is not in RUN state, put it in to 'RUN'
>    state.

And what is the problem if controller is put in PAUSED state, FIFO
filled with data and then RUN again, like in v2 of this patch?

<snip>

> > > 
> > > -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >   {
> > > -       u32 opflags;
> > >          u32 val = 0;
> > >          int idx;
> > > +       int len = msg->len + qup->rx_tag_len;
> > 
> > Is this intentional?
> > 
>     Yes, since i changed the loop around qup_i2c_read_one to count for
>     blocks. 

No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and 
I don't see how this is related to counting blocks, in this function.

<snip>

> > > 
> > > -       qup_i2c_issue_read(qup, msg);
> > > +               qup_i2c_issue_read(qup, msg);
> > > 
> > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > -       if (ret)
> > > -               goto err;
> > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > +               if (ret)
> > > +                       goto err;
> > > 
> > > -       do {
> > >                  left = wait_for_completion_timeout(&qup->xfer, HZ);
> > >                  if (!left) {
> > >                          writel(1, qup->base + QUP_SW_RESET);
> > > @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >                  }
> > > 
> > >                  qup_i2c_read_fifo(qup, msg);
> > > -       } while (qup->pos < msg->len);
> > > +               qup->blk.block_pos++;
> > 
> > This should not be incremented, unless we really have read this block.
> > 
>    We are reading it and only then incrementing it.

But read FIFO function could exit because of timeout, which is
not checked. The same is true for write operations.

Somehow this patch looks overly complex, I don't believe
that it should be.

Ivan.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-15  8:49           ` Ivan T. Ivanov
  0 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-15  8:49 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Sricharan,

On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:

> > > +/* frequency definitions for high speed and max speed */
> > > +#define I2C_QUP_CLK_FAST_FREQ          1000000
> > 
> > This is fast mode, if I am not mistaken.
> > 
>   ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>   We use this macro to check if the desired freq is in HS range.
>   The above comment can be changed though to make it clear.

My point was that this is neither high nor max speed.

> > > +
> > >   /* Status, Error flags */
> > >   #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
> > >   #define I2C_STATUS_BUS_ACTIVE          BIT(8)
> > > @@ -102,6 +119,15 @@
> > >   #define RESET_BIT                      0x0
> > >   #define ONE_BYTE                       0x1
> > > 
> > > +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
> > 
> > Could you explain what is this for?
> > 
>    This is a new feature in the V2 version of the controller,
>    to support multiple i2c sub transfers without having
>    a 'stop' bit in-between. Without this the i2c controller
>    inserts a 'stop' on the bus when the WR/RD count registers
>    reaches zero and are configured for the next transfer. So setting
>    this bit when the controller is in 'RUN' state, avoids sending the
>    'stop' during RUN state.
>    I can add this comment in the patch.

And how v2 of this patch was worked if you introduce this bit now?
Bit is also not used by downstream driver, AFICS?

> 
> > > +
> > > +struct qup_i2c_block {
> > > +       int     blocks;

count

> > > +       u8      *block_tag_len;

just tag_len, 

> > > +       int     *block_data_len;

just data_len,

> > > +       int     block_pos;

just pos?

> > > +};
> > > +
> > >   struct qup_i2c_dev {
> > >          struct device*dev;
> > >          void __iomem*base;
> > > @@ -115,9 +141,17 @@ struct qup_i2c_dev {
> > >          int     in_fifo_sz;
> > >          int     out_blk_sz;
> > >          int     in_blk_sz;
> > > -
> > > +       struct  qup_i2c_blockblk;
> > >          unsigned longone_byte_t;
> > > 
> > > +       int     is_hs;
> > > +       bool    use_v2_tags;
> > > +
> > > +       int     tx_tag_len;
> > > +       int     rx_tag_len;
> > > +       u8      *tags;
> > > +       int     tags_pos;
> > > +
> > >          struct i2c_msg*msg;
> > >          /* Current posion in user message buffer */
> > >          int     pos;
> > > @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
> > >          }
> > >   }
> > 
> > Is this better tag related fields grouping?
> > 
> 
> > struct qup_i2c_tag_block {
> > 
> >          u8      tag[2];
> >          // int  tag_len; this is alway 2, or?
> >          int     data_len; // this could be zero, right?
> > };
> > 
> There is a struct for qup_i2c_block which has tag and data len. Not sure
> what change you suggest above ? Also with V2 transfers tag len need
>   not be 2. It can be more than that based on the data len.

The point is that: I will like to see better grouping of
related variables. Now they are spread all over. Would it
be possible to also take care for tx_tag_len, rx_tag_len, 
tags, tags_pos.

> 
> > > -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > +                                                       int run)
> > 
> > And 'run' stands for?
>   'run' just says whether the controller is in 'RUN' or 'RESET' state.
>    I can change it to is_run_st to make it clear.
> > >   {
> > > -       /* Number of entries to shift out, including the start */
> > > -       int total = msg->len + 1;
> > > +       /* Total Number of entries to shift out, including the tags */
> > > +       int total;
> > > +
> > > +       if (qup->use_v2_tags) {
> > > +               total = msg->len + qup->tx_tag_len;
> > > +               if (run)
> > > +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
> > 
> > What?
> > 
>       This means, if the controller is in 'RUN' state, for
>       reconfiguring the RD/WR counts this bit has to be set to avoid
>       'stop' bits.

I don't buy it, sorry. Problem with v1 of the tags is that controller
can not read more than 256 bytes without automatically generate STOP
at the end, because transfer length specified with QUP_TAG_REC tag
is 8 bits wide. There is no limitation for writes with v1 tags,
because controller is explicitly instructed when to send out STOP.

For v2 of the tags, writes behaves more or less the same, and the
good news are that there is new read tag QUP_TAG_V2_DATARD, which 
did't generate STOP when specified amount of data is read, still
up to 256 bytes in chunk. Read transfers with size more than 256
could be formed in following way:

V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.

> 
> > > 
> > > -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
> > > +                                               struct i2c_msg *msg, int last)
> > > +{
> > > +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
> > > +       int len = 0, prev_len = 0;
> > > +       int blocks = 0;
> > > +       int rem;
> > > +       int block_len = 0;
> > > +       int data_len;
> > > +
> > > +       qup->blk.block_pos = 0;
> > > +       qup->pos = 0;
> > > +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
> > > +       rem = msg->len % QUP_READ_LIMIT;
> > > +
> > > +       /* 2 tag bytes for each block + 2 extra bytes for first block */
> > > +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
> > > +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
> > > +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
> > > +                                               qup->blk.blocks, GFP_KERNEL);
> > 
> > Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
> > 
> > 
> > Allocations could fail and memory is leaking here.
> > 
>   ya correct, will change this. Freeing is done at the end of xfer
>   function, but will have to check for allocation failure.

Do you see how memory leak here? 

> 
> > > +
> > > +       while (blocks < qup->blk.blocks) {
> > > 
> > > +               blocks++;
> > 
> > Looks like 'for' cycle to me.
> > 
>   sorry, not getting it ?

This 'while' loop is old plain 'for'.

> > > +       }
> > > +
> > > +       qup->tx_tag_len = len;
> > > +
> > > +       if (msg->flags & I2C_M_RD)
> > > +               qup->rx_tag_len = (qup->blk.blocks * 2);

This will need some explanation.


> > > +
> > > +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +{
> > > +       u32 data_len = 0, tag_len;
> > > +
> > > +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> > > +
> > > +       if (!(msg->flags & I2C_M_RD))
> > > +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> > > +
> > > +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
> > 
> > This assumes that writes are up to 256 bytes, and tags and data blocks
> > are completely written to FIFO buffer, right?
> > 
>   Yes, since we send/read data in blocks (256 bytes).

How deep is the FIFO? Is it guaranteed that "the whole" write 
or read data, including tags will fit in.

> > > 
> > > +
> > > +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > +                                                               int run, int last)
> > >   {
> > >          unsigned long left;
> > >          int ret;
> > > @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >          qup->msg = msg;
> > >          qup->pos = 0;
> > > 
> > > +       if (qup->use_v2_tags)
> > > +               qup_i2c_create_tag_v2(qup, msg, last);
> > > +       else
> > > +               qup->blk.blocks = 0;
> > > +
> > >          enable_irq(qup->irq);
> > > 
> > > -       qup_i2c_set_write_mode(qup, msg);
> > > +       qup_i2c_set_write_mode(qup, msg, run);
> > > 
> > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > -       if (ret)
> > > -               goto err;
> > > +       if (!run) {
> > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > 
> > To run away, or not?
> > 
>    Means, if the controller is not in RUN state, put it in to 'RUN'
>    state.

And what is the problem if controller is put in PAUSED state, FIFO
filled with data and then RUN again, like in v2 of this patch?

<snip>

> > > 
> > > -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >   {
> > > -       u32 opflags;
> > >          u32 val = 0;
> > >          int idx;
> > > +       int len = msg->len + qup->rx_tag_len;
> > 
> > Is this intentional?
> > 
>     Yes, since i changed the loop around qup_i2c_read_one to count for
>     blocks. 

No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and 
I don't see how this is related to counting blocks, in this function.

<snip>

> > > 
> > > -       qup_i2c_issue_read(qup, msg);
> > > +               qup_i2c_issue_read(qup, msg);
> > > 
> > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > -       if (ret)
> > > -               goto err;
> > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > +               if (ret)
> > > +                       goto err;
> > > 
> > > -       do {
> > >                  left = wait_for_completion_timeout(&qup->xfer, HZ);
> > >                  if (!left) {
> > >                          writel(1, qup->base + QUP_SW_RESET);
> > > @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > >                  }
> > > 
> > >                  qup_i2c_read_fifo(qup, msg);
> > > -       } while (qup->pos < msg->len);
> > > +               qup->blk.block_pos++;
> > 
> > This should not be incremented, unless we really have read this block.
> > 
>    We are reading it and only then incrementing it.

But read FIFO function could exit because of timeout, which is
not checked. The same is true for write operations.

Somehow this patch looks overly complex, I don't believe
that it should be.

Ivan.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-15  8:49           ` Ivan T. Ivanov
@ 2015-04-15 13:20             ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15 13:20 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel

Hi Ivan,

On 04/15/2015 02:19 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:
>
>>>> +/* frequency definitions for high speed and max speed */
>>>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>>>
>>> This is fast mode, if I am not mistaken.
>>>
>>    ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>>    We use this macro to check if the desired freq is in HS range.
>>    The above comment can be changed though to make it clear.
>
> My point was that this is neither high nor max speed.
>
I see that QUP specs defines up to 1MHZ as fast+ speed.

>>>> +
>>>>    /* Status, Error flags */
>>>>    #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>>>    #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>>>> @@ -102,6 +119,15 @@
>>>>    #define RESET_BIT                      0x0
>>>>    #define ONE_BYTE                       0x1
>>>>
>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>
>>> Could you explain what is this for?
>>>
>>     This is a new feature in the V2 version of the controller,
>>     to support multiple i2c sub transfers without having
>>     a 'stop' bit in-between. Without this the i2c controller
>>     inserts a 'stop' on the bus when the WR/RD count registers
>>     reaches zero and are configured for the next transfer. So setting
>>     this bit when the controller is in 'RUN' state, avoids sending the
>>     'stop' during RUN state.
>>     I can add this comment in the patch.
>
> And how v2 of this patch was worked if you introduce this bit now?
> Bit is also not used by downstream driver, AFICS?
>
The one of the reason for this and the bam support patches in this 
series was to support multiple transfers of i2c_msgs without a 'stop' 
inbetween them. So without that the driver sends a 'stop' between each 
sub-transfer. The v2 of this series supported that only in bam mode
and not in non-bam mode. That was a bug. I saw the difference in 
behavior between bam and non-bam mode while testing with a hdmi adv 
bridge recently. So added the support in this series. This was neede to 
bringup the HDMI adv bridge device. I could have added it as a new patch 
to make it more explicit.

>>
>>>> +
>>>> +struct qup_i2c_block {
>>>> +       int     blocks;
>
> count
>
>>>> +       u8      *block_tag_len;
>
> just tag_len,
>
>>>> +       int     *block_data_len;
>
> just data_len,
>
>>>> +       int     block_pos;
>
> just pos?
>

>>>> +};
>>>> +
>>>>    struct qup_i2c_dev {
>>>>           struct device*dev;
>>>>           void __iomem*base;
>>>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>>>           int     in_fifo_sz;
>>>>           int     out_blk_sz;
>>>>           int     in_blk_sz;
>>>> -
>>>> +       struct  qup_i2c_blockblk;
>>>>           unsigned longone_byte_t;
>>>>
>>>> +       int     is_hs;
>>>> +       bool    use_v2_tags;
>>>> +
>>>> +       int     tx_tag_len;
>>>> +       int     rx_tag_len;
>>>> +       u8      *tags;
>>>> +       int     tags_pos;
>>>> +
>>>>           struct i2c_msg*msg;
>>>>           /* Current posion in user message buffer */
>>>>           int     pos;
>>>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>>>           }
>>>>    }
>>>
>>> Is this better tag related fields grouping?
>>>
>>
>>> struct qup_i2c_tag_block {
>>>
>>>           u8      tag[2];
>>>           // int  tag_len; this is alway 2, or?
>>>           int     data_len; // this could be zero, right?
>>> };
>>>
>> There is a struct for qup_i2c_block which has tag and data len. Not sure
>> what change you suggest above ? Also with V2 transfers tag len need
>>    not be 2. It can be more than that based on the data len.
>
> The point is that: I will like to see better grouping of
> related variables. Now they are spread all over. Would it
> be possible to also take care for tx_tag_len, rx_tag_len,
> tags, tags_pos.
>

For this and the above, i will change the groupings and split this patch 
in to couple of smaller ones.

>>
>>>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                       int run)
>>>
>>> And 'run' stands for?
>>    'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>     I can change it to is_run_st to make it clear.
>>>>    {
>>>> -       /* Number of entries to shift out, including the start */
>>>> -       int total = msg->len + 1;
>>>> +       /* Total Number of entries to shift out, including the tags */
>>>> +       int total;
>>>> +
>>>> +       if (qup->use_v2_tags) {
>>>> +               total = msg->len + qup->tx_tag_len;
>>>> +               if (run)
>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>
>>> What?
>>>
>>        This means, if the controller is in 'RUN' state, for
>>        reconfiguring the RD/WR counts this bit has to be set to avoid
>>        'stop' bits.
>
> I don't buy it, sorry. Problem with v1 of the tags is that controller
> can not read more than 256 bytes without automatically generate STOP
> at the end, because transfer length specified with QUP_TAG_REC tag
> is 8 bits wide. There is no limitation for writes with v1 tags,
> because controller is explicitly instructed when to send out STOP.
>
correct till this.

> For v2 of the tags, writes behaves more or less the same, and the
> good news are that there is new read tag QUP_TAG_V2_DATARD, which
> did't generate STOP when specified amount of data is read, still
> up to 256 bytes in chunk. Read transfers with size more than 256
> could be formed in following way:
>
> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>
  The above is true for a single subtransfer for reading/writing more 
than > 256 bytes. But for doing WRITE, READ kind of sub transfers once 
the first sub transfer (write) is over, and while re-configuring the
_COUNT registers for the next transfers, 'a stop' between is inserted.
To avoid this , the MX_CONFIG_DURING_RUN bit should be set while in 
'RUN' state, before re-configuring for the next sub transfer. The
qup spec calls this as bus 'lock-unlock' feature.

I tested this and it fixed the wrong data reads in the case of the hdmi 
adv bridge reads. It was doing 2 i2c_msgs transfers for each i2c_xfer 
call.  The data read was wrong without this patch in v1 mode (default)
and even in v2 mode without the lock-unlock even though we do not send
a 'STOP' tag command between sub-transfers.

>>
>>>>
>>>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>>>> +                                               struct i2c_msg *msg, int last)
>>>> +{
>>>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>>>> +       int len = 0, prev_len = 0;
>>>> +       int blocks = 0;
>>>> +       int rem;
>>>> +       int block_len = 0;
>>>> +       int data_len;
>>>> +
>>>> +       qup->blk.block_pos = 0;
>>>> +       qup->pos = 0;
>>>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>>>> +       rem = msg->len % QUP_READ_LIMIT;
>>>> +
>>>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>>>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>>>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>>>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>>>> +                                               qup->blk.blocks, GFP_KERNEL);
>>>
>>> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>>>
>>>
>>> Allocations could fail and memory is leaking here.
>>>
>>    ya correct, will change this. Freeing is done at the end of xfer
>>    function, but will have to check for allocation failure.
>
> Do you see how memory leak here?
if the first allocation pass and second one fails, and i will have
to move the kfree calls at the end of i2c_xfer inside the loop.

>
>>
>>>> +
>>>> +       while (blocks < qup->blk.blocks) {
>>>>
>>>> +               blocks++;
>>>
>>> Looks like 'for' cycle to me.
>>>
>>    sorry, not getting it ?
>
> This 'while' loop is old plain 'for'.
>
  ok
>>>> +       }
>>>> +
>>>> +       qup->tx_tag_len = len;
>>>> +
>>>> +       if (msg->flags & I2C_M_RD)
>>>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>
> This will need some explanation.
>
ok, will add it.
>
>>>> +
>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +{
>>>> +       u32 data_len = 0, tag_len;
>>>> +
>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>> +
>>>> +       if (!(msg->flags & I2C_M_RD))
>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>> +
>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>
>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>> are completely written to FIFO buffer, right?
>>>
>>    Yes, since we send/read data in blocks (256 bytes).
>
> How deep is the FIFO? Is it guaranteed that "the whole" write
> or read data, including tags will fit in.
>
  Write/read fifo functions (also for V1) currently wait for the fifo
  full and empty flags conditions. This will ensure that the fifo full
  and empty conditions are taken care before writing and reading. But
  this can be improved by waiting for block_write/read flags to improve
  the throughput.

>>>>
>>>> +
>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                               int run, int last)
>>>>    {
>>>>           unsigned long left;
>>>>           int ret;
>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>           qup->msg = msg;
>>>>           qup->pos = 0;
>>>>
>>>> +       if (qup->use_v2_tags)
>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>> +       else
>>>> +               qup->blk.blocks = 0;
>>>> +
>>>>           enable_irq(qup->irq);
>>>>
>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +       if (!run) {
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>
>>> To run away, or not?
>>>
>>     Means, if the controller is not in RUN state, put it in to 'RUN'
>>     state.
>
> And what is the problem if controller is put in PAUSED state, FIFO
> filled with data and then RUN again, like in v2 of this patch?
>
  This function is not entered with controller in PAUSED state.
  Only in Reset state (for the first transfer) and Run state for the
  subsequent sub-transfers. The reason for having this 'run' variable
   was that while using the lock-unlock feature, the controller should
  not be put in to run-reset-run state in-between transfers.

> <snip>
>
>>>>
>>>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>    {
>>>> -       u32 opflags;
>>>>           u32 val = 0;
>>>>           int idx;
>>>> +       int len = msg->len + qup->rx_tag_len;
>>>
>>> Is this intentional?
>>>
>>      Yes, since i changed the loop around qup_i2c_read_one to count for
>>      blocks.
>
> No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and
> I don't see how this is related to counting blocks, in this function.
>
  sorry. Did confuse my response last time. This +rx_tag_len is not 
needed here and infact it is '0' in case of v1. So no effect.

> <snip>
>
>>>>
>>>> -       qup_i2c_issue_read(qup, msg);
>>>> +               qup_i2c_issue_read(qup, msg);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> +               if (ret)
>>>> +                       goto err;
>>>>
>>>> -       do {
>>>>                   left = wait_for_completion_timeout(&qup->xfer, HZ);
>>>>                   if (!left) {
>>>>                           writel(1, qup->base + QUP_SW_RESET);
>>>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>                   }
>>>>
>>>>                   qup_i2c_read_fifo(qup, msg);
>>>> -       } while (qup->pos < msg->len);
>>>> +               qup->blk.block_pos++;
>>>
>>> This should not be incremented, unless we really have read this block.
>>>
>>     We are reading it and only then incrementing it.
>
> But read FIFO function could exit because of timeout, which is
> not checked. The same is true for write operations.
>
> Somehow this patch looks overly complex, I don't believe
> that it should be.
>
ok, the read and write fifo timing out error checks should be corrected
once i check the error code for qup_i2c_wait_ready function.

I will split this patch in to couple of smaller patches and make sure it 
does not look complex.

Regards,
  Sricharan

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-15 13:20             ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ivan,

On 04/15/2015 02:19 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:
>
>>>> +/* frequency definitions for high speed and max speed */
>>>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>>>
>>> This is fast mode, if I am not mistaken.
>>>
>>    ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>>    We use this macro to check if the desired freq is in HS range.
>>    The above comment can be changed though to make it clear.
>
> My point was that this is neither high nor max speed.
>
I see that QUP specs defines up to 1MHZ as fast+ speed.

>>>> +
>>>>    /* Status, Error flags */
>>>>    #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>>>    #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>>>> @@ -102,6 +119,15 @@
>>>>    #define RESET_BIT                      0x0
>>>>    #define ONE_BYTE                       0x1
>>>>
>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>
>>> Could you explain what is this for?
>>>
>>     This is a new feature in the V2 version of the controller,
>>     to support multiple i2c sub transfers without having
>>     a 'stop' bit in-between. Without this the i2c controller
>>     inserts a 'stop' on the bus when the WR/RD count registers
>>     reaches zero and are configured for the next transfer. So setting
>>     this bit when the controller is in 'RUN' state, avoids sending the
>>     'stop' during RUN state.
>>     I can add this comment in the patch.
>
> And how v2 of this patch was worked if you introduce this bit now?
> Bit is also not used by downstream driver, AFICS?
>
The one of the reason for this and the bam support patches in this 
series was to support multiple transfers of i2c_msgs without a 'stop' 
inbetween them. So without that the driver sends a 'stop' between each 
sub-transfer. The v2 of this series supported that only in bam mode
and not in non-bam mode. That was a bug. I saw the difference in 
behavior between bam and non-bam mode while testing with a hdmi adv 
bridge recently. So added the support in this series. This was neede to 
bringup the HDMI adv bridge device. I could have added it as a new patch 
to make it more explicit.

>>
>>>> +
>>>> +struct qup_i2c_block {
>>>> +       int     blocks;
>
> count
>
>>>> +       u8      *block_tag_len;
>
> just tag_len,
>
>>>> +       int     *block_data_len;
>
> just data_len,
>
>>>> +       int     block_pos;
>
> just pos?
>

>>>> +};
>>>> +
>>>>    struct qup_i2c_dev {
>>>>           struct device*dev;
>>>>           void __iomem*base;
>>>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>>>           int     in_fifo_sz;
>>>>           int     out_blk_sz;
>>>>           int     in_blk_sz;
>>>> -
>>>> +       struct  qup_i2c_blockblk;
>>>>           unsigned longone_byte_t;
>>>>
>>>> +       int     is_hs;
>>>> +       bool    use_v2_tags;
>>>> +
>>>> +       int     tx_tag_len;
>>>> +       int     rx_tag_len;
>>>> +       u8      *tags;
>>>> +       int     tags_pos;
>>>> +
>>>>           struct i2c_msg*msg;
>>>>           /* Current posion in user message buffer */
>>>>           int     pos;
>>>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>>>           }
>>>>    }
>>>
>>> Is this better tag related fields grouping?
>>>
>>
>>> struct qup_i2c_tag_block {
>>>
>>>           u8      tag[2];
>>>           // int  tag_len; this is alway 2, or?
>>>           int     data_len; // this could be zero, right?
>>> };
>>>
>> There is a struct for qup_i2c_block which has tag and data len. Not sure
>> what change you suggest above ? Also with V2 transfers tag len need
>>    not be 2. It can be more than that based on the data len.
>
> The point is that: I will like to see better grouping of
> related variables. Now they are spread all over. Would it
> be possible to also take care for tx_tag_len, rx_tag_len,
> tags, tags_pos.
>

For this and the above, i will change the groupings and split this patch 
in to couple of smaller ones.

>>
>>>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                       int run)
>>>
>>> And 'run' stands for?
>>    'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>     I can change it to is_run_st to make it clear.
>>>>    {
>>>> -       /* Number of entries to shift out, including the start */
>>>> -       int total = msg->len + 1;
>>>> +       /* Total Number of entries to shift out, including the tags */
>>>> +       int total;
>>>> +
>>>> +       if (qup->use_v2_tags) {
>>>> +               total = msg->len + qup->tx_tag_len;
>>>> +               if (run)
>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>
>>> What?
>>>
>>        This means, if the controller is in 'RUN' state, for
>>        reconfiguring the RD/WR counts this bit has to be set to avoid
>>        'stop' bits.
>
> I don't buy it, sorry. Problem with v1 of the tags is that controller
> can not read more than 256 bytes without automatically generate STOP
> at the end, because transfer length specified with QUP_TAG_REC tag
> is 8 bits wide. There is no limitation for writes with v1 tags,
> because controller is explicitly instructed when to send out STOP.
>
correct till this.

> For v2 of the tags, writes behaves more or less the same, and the
> good news are that there is new read tag QUP_TAG_V2_DATARD, which
> did't generate STOP when specified amount of data is read, still
> up to 256 bytes in chunk. Read transfers with size more than 256
> could be formed in following way:
>
> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>
  The above is true for a single subtransfer for reading/writing more 
than > 256 bytes. But for doing WRITE, READ kind of sub transfers once 
the first sub transfer (write) is over, and while re-configuring the
_COUNT registers for the next transfers, 'a stop' between is inserted.
To avoid this , the MX_CONFIG_DURING_RUN bit should be set while in 
'RUN' state, before re-configuring for the next sub transfer. The
qup spec calls this as bus 'lock-unlock' feature.

I tested this and it fixed the wrong data reads in the case of the hdmi 
adv bridge reads. It was doing 2 i2c_msgs transfers for each i2c_xfer 
call.  The data read was wrong without this patch in v1 mode (default)
and even in v2 mode without the lock-unlock even though we do not send
a 'STOP' tag command between sub-transfers.

>>
>>>>
>>>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>>>> +                                               struct i2c_msg *msg, int last)
>>>> +{
>>>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>>>> +       int len = 0, prev_len = 0;
>>>> +       int blocks = 0;
>>>> +       int rem;
>>>> +       int block_len = 0;
>>>> +       int data_len;
>>>> +
>>>> +       qup->blk.block_pos = 0;
>>>> +       qup->pos = 0;
>>>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>>>> +       rem = msg->len % QUP_READ_LIMIT;
>>>> +
>>>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>>>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>>>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>>>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>>>> +                                               qup->blk.blocks, GFP_KERNEL);
>>>
>>> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>>>
>>>
>>> Allocations could fail and memory is leaking here.
>>>
>>    ya correct, will change this. Freeing is done at the end of xfer
>>    function, but will have to check for allocation failure.
>
> Do you see how memory leak here?
if the first allocation pass and second one fails, and i will have
to move the kfree calls at the end of i2c_xfer inside the loop.

>
>>
>>>> +
>>>> +       while (blocks < qup->blk.blocks) {
>>>>
>>>> +               blocks++;
>>>
>>> Looks like 'for' cycle to me.
>>>
>>    sorry, not getting it ?
>
> This 'while' loop is old plain 'for'.
>
  ok
>>>> +       }
>>>> +
>>>> +       qup->tx_tag_len = len;
>>>> +
>>>> +       if (msg->flags & I2C_M_RD)
>>>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>
> This will need some explanation.
>
ok, will add it.
>
>>>> +
>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +{
>>>> +       u32 data_len = 0, tag_len;
>>>> +
>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>> +
>>>> +       if (!(msg->flags & I2C_M_RD))
>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>> +
>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>
>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>> are completely written to FIFO buffer, right?
>>>
>>    Yes, since we send/read data in blocks (256 bytes).
>
> How deep is the FIFO? Is it guaranteed that "the whole" write
> or read data, including tags will fit in.
>
  Write/read fifo functions (also for V1) currently wait for the fifo
  full and empty flags conditions. This will ensure that the fifo full
  and empty conditions are taken care before writing and reading. But
  this can be improved by waiting for block_write/read flags to improve
  the throughput.

>>>>
>>>> +
>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                               int run, int last)
>>>>    {
>>>>           unsigned long left;
>>>>           int ret;
>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>           qup->msg = msg;
>>>>           qup->pos = 0;
>>>>
>>>> +       if (qup->use_v2_tags)
>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>> +       else
>>>> +               qup->blk.blocks = 0;
>>>> +
>>>>           enable_irq(qup->irq);
>>>>
>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +       if (!run) {
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>
>>> To run away, or not?
>>>
>>     Means, if the controller is not in RUN state, put it in to 'RUN'
>>     state.
>
> And what is the problem if controller is put in PAUSED state, FIFO
> filled with data and then RUN again, like in v2 of this patch?
>
  This function is not entered with controller in PAUSED state.
  Only in Reset state (for the first transfer) and Run state for the
  subsequent sub-transfers. The reason for having this 'run' variable
   was that while using the lock-unlock feature, the controller should
  not be put in to run-reset-run state in-between transfers.

> <snip>
>
>>>>
>>>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>    {
>>>> -       u32 opflags;
>>>>           u32 val = 0;
>>>>           int idx;
>>>> +       int len = msg->len + qup->rx_tag_len;
>>>
>>> Is this intentional?
>>>
>>      Yes, since i changed the loop around qup_i2c_read_one to count for
>>      blocks.
>
> No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and
> I don't see how this is related to counting blocks, in this function.
>
  sorry. Did confuse my response last time. This +rx_tag_len is not 
needed here and infact it is '0' in case of v1. So no effect.

> <snip>
>
>>>>
>>>> -       qup_i2c_issue_read(qup, msg);
>>>> +               qup_i2c_issue_read(qup, msg);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> +               if (ret)
>>>> +                       goto err;
>>>>
>>>> -       do {
>>>>                   left = wait_for_completion_timeout(&qup->xfer, HZ);
>>>>                   if (!left) {
>>>>                           writel(1, qup->base + QUP_SW_RESET);
>>>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>                   }
>>>>
>>>>                   qup_i2c_read_fifo(qup, msg);
>>>> -       } while (qup->pos < msg->len);
>>>> +               qup->blk.block_pos++;
>>>
>>> This should not be incremented, unless we really have read this block.
>>>
>>     We are reading it and only then incrementing it.
>
> But read FIFO function could exit because of timeout, which is
> not checked. The same is true for write operations.
>
> Somehow this patch looks overly complex, I don't believe
> that it should be.
>
ok, the read and write fifo timing out error checks should be corrected
once i check the error code for qup_i2c_wait_ready function.

I will split this patch in to couple of smaller patches and make sure it 
does not look complex.

Regards,
  Sricharan

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-15  8:49           ` Ivan T. Ivanov
@ 2015-04-15 14:44             ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15 14:44 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel

Hi Ivan,

   Sorry resending again, because wrapping seemed to be
   somehow wrong in my previous response.

On 04/15/2015 02:19 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:
>
>>>> +/* frequency definitions for high speed and max speed */
>>>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>>>
>>> This is fast mode, if I am not mistaken.
>>>
>>    ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>>    We use this macro to check if the desired freq is in HS range.
>>    The above comment can be changed though to make it clear.
>
> My point was that this is neither high nor max speed.
>
I see that QUP specs defines up to 1MHZ as fast+ speed.
>>>> +
>>>>    /* Status, Error flags */
>>>>    #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>>>    #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>>>> @@ -102,6 +119,15 @@
>>>>    #define RESET_BIT                      0x0
>>>>    #define ONE_BYTE                       0x1
>>>>
>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>
>>> Could you explain what is this for?
>>>
>>     This is a new feature in the V2 version of the controller,
>>     to support multiple i2c sub transfers without having
>>     a 'stop' bit in-between. Without this the i2c controller
>>     inserts a 'stop' on the bus when the WR/RD count registers
>>     reaches zero and are configured for the next transfer. So setting
>>     this bit when the controller is in 'RUN' state, avoids sending the
>>     'stop' during RUN state.
>>     I can add this comment in the patch.
>
> And how v2 of this patch was worked if you introduce this bit now?
> Bit is also not used by downstream driver, AFICS?
>
The one of the reason for this and the bam support patches in
this series was to support multiple transfers of i2c_msgs without
  a 'stop' inbetween them. So without that the driver sends a 'stop'
between each sub-transfer. The v2 of this series supported that only in
bam mode and not in non-bam mode. That was a bug. I saw the difference
in behavior between bam and non-bam mode while testing with a hdmi adv
bridge recently. So added the support in this series. This was neede to
bringup the HDMI adv bridge device. I could have added it as a
  new patch to make it more explicit.

>>
>>>> +
>>>> +struct qup_i2c_block {
>>>> +       int     blocks;
>
> count
>
>>>> +       u8      *block_tag_len;
>
> just tag_len,
>
>>>> +       int     *block_data_len;
>
> just data_len,
>
>>>> +       int     block_pos;
>
> just pos?
>
>>>> +};
>>>> +
>>>>    struct qup_i2c_dev {
>>>>           struct device*dev;
>>>>           void __iomem*base;
>>>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>>>           int     in_fifo_sz;
>>>>           int     out_blk_sz;
>>>>           int     in_blk_sz;
>>>> -
>>>> +       struct  qup_i2c_blockblk;
>>>>           unsigned longone_byte_t;
>>>>
>>>> +       int     is_hs;
>>>> +       bool    use_v2_tags;
>>>> +
>>>> +       int     tx_tag_len;
>>>> +       int     rx_tag_len;
>>>> +       u8      *tags;
>>>> +       int     tags_pos;
>>>> +
>>>>           struct i2c_msg*msg;
>>>>           /* Current posion in user message buffer */
>>>>           int     pos;
>>>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>>>           }
>>>>    }
>>>
>>> Is this better tag related fields grouping?
>>>
>>
>>> struct qup_i2c_tag_block {
>>>
>>>           u8      tag[2];
>>>           // int  tag_len; this is alway 2, or?
>>>           int     data_len; // this could be zero, right?
>>> };
>>>
>> There is a struct for qup_i2c_block which has tag and data len. Not sure
>> what change you suggest above ? Also with V2 transfers tag len need
>>    not be 2. It can be more than that based on the data len.
>
> The point is that: I will like to see better grouping of
> related variables. Now they are spread all over. Would it
> be possible to also take care for tx_tag_len, rx_tag_len,
> tags, tags_pos.
>
For this and the above, i will change the groupings and split this patch
  in to couple of smaller ones.
>>
>>>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                       int run)
>>>
>>> And 'run' stands for?
>>    'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>     I can change it to is_run_st to make it clear.
>>>>    {
>>>> -       /* Number of entries to shift out, including the start */
>>>> -       int total = msg->len + 1;
>>>> +       /* Total Number of entries to shift out, including the tags */
>>>> +       int total;
>>>> +
>>>> +       if (qup->use_v2_tags) {
>>>> +               total = msg->len + qup->tx_tag_len;
>>>> +               if (run)
>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>
>>> What?
>>>
>>        This means, if the controller is in 'RUN' state, for
>>        reconfiguring the RD/WR counts this bit has to be set to avoid
>>        'stop' bits.
>
> I don't buy it, sorry. Problem with v1 of the tags is that controller
> can not read more than 256 bytes without automatically generate STOP
> at the end, because transfer length specified with QUP_TAG_REC tag
> is 8 bits wide. There is no limitation for writes with v1 tags,
> because controller is explicitly instructed when to send out STOP.
>
correct till this.

> For v2 of the tags, writes behaves more or less the same, and the
> good news are that there is new read tag QUP_TAG_V2_DATARD, which
> did't generate STOP when specified amount of data is read, still
> up to 256 bytes in chunk. Read transfers with size more than 256
> could be formed in following way:
>
> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>
  The above is true for a single subtransfer for reading/writing
more than > 256 bytes. But for doing WRITE, READ kind of sub
  transfers once the first sub transfer (write) is over, and
  while re-configuring the _COUNT registers for the next transfers,
'a stop' between is inserted.
To avoid this,the MX_CONFIG_DURING_RUN  bit should be set while in
  'RUN' state, before re-configuring for the next sub transfer.
  The qupspec calls this as bus 'lock-unlock' feature.

I tested this and it fixed the wrong data reads in the case of the hdmi
adv bridge reads. It was doing 2 i2c_msgs transfers for each i2c_xfer
call.  The data read was wrong without this patch in v1 mode (default)
and even in v2 mode without the lock-unlock even though we do not send
a 'STOP' tag command between sub-transfers.

>>
>>>>
>>>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>>>> +                                               struct i2c_msg *msg, int last)
>>>> +{
>>>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>>>> +       int len = 0, prev_len = 0;
>>>> +       int blocks = 0;
>>>> +       int rem;
>>>> +       int block_len = 0;
>>>> +       int data_len;
>>>> +
>>>> +       qup->blk.block_pos = 0;
>>>> +       qup->pos = 0;
>>>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>>>> +       rem = msg->len % QUP_READ_LIMIT;
>>>> +
>>>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>>>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>>>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>>>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>>>> +                                               qup->blk.blocks, GFP_KERNEL);
>>>
>>> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>>>
>>>
>>> Allocations could fail and memory is leaking here.
>>>
>>    ya correct, will change this. Freeing is done at the end of xfer
>>    function, but will have to check for allocation failure.
>
> Do you see how memory leak here?
>
if the first allocation pass and second one fails, and i will have
to move the kfree calls at the end of i2c_xfer inside the loop.
>>
>>>> +
>>>> +       while (blocks < qup->blk.blocks) {
>>>>
>>>> +               blocks++;
>>>
>>> Looks like 'for' cycle to me.
>>>
>>    sorry, not getting it ?
>
> This 'while' loop is old plain 'for'.
>
ok
>>>> +       }
>>>> +
>>>> +       qup->tx_tag_len = len;
>>>> +
>>>> +       if (msg->flags & I2C_M_RD)
>>>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>
> This will need some explanation.
>
ok, will add it.

>
>>>> +
>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +{
>>>> +       u32 data_len = 0, tag_len;
>>>> +
>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>> +
>>>> +       if (!(msg->flags & I2C_M_RD))
>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>> +
>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>
>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>> are completely written to FIFO buffer, right?
>>>
>>    Yes, since we send/read data in blocks (256 bytes).
>
> How deep is the FIFO? Is it guaranteed that "the whole" write
> or read data, including tags will fit in.
>
  Write/read fifo functions (also for V1) currently wait for the
   fifo full and empty flags conditions. This will ensure that the
  fifo full and empty conditions are taken care before writing
  and reading. But this can be improved by waiting for
  block_write/read flags to improve the throughput.

>>>>
>>>> +
>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                               int run, int last)
>>>>    {
>>>>           unsigned long left;
>>>>           int ret;
>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>           qup->msg = msg;
>>>>           qup->pos = 0;
>>>>
>>>> +       if (qup->use_v2_tags)
>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>> +       else
>>>> +               qup->blk.blocks = 0;
>>>> +
>>>>           enable_irq(qup->irq);
>>>>
>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +       if (!run) {
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>
>>> To run away, or not?
>>>
>>     Means, if the controller is not in RUN state, put it in to 'RUN'
>>     state.
>
> And what is the problem if controller is put in PAUSED state, FIFO
> filled with data and then RUN again, like in v2 of this patch?
>
  This function is not entered with controller in PAUSED state
  Only in Reset state (for the first transfer) and Run state for
  the subsequent sub-transfers. The reason for having this 'run'
  variable was that while using the lock-unlock feature, the
  controller should not be put in to run-reset-run state
  in-between transfers.

> <snip>
>
>>>>
>>>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>    {
>>>> -       u32 opflags;
>>>>           u32 val = 0;
>>>>           int idx;
>>>> +       int len = msg->len + qup->rx_tag_len;
>>>
>>> Is this intentional?
>>>
>>      Yes, since i changed the loop around qup_i2c_read_one to count for
>>      blocks.
>
> No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and
> I don't see how this is related to counting blocks, in this function.
>
  sorry. Did confuse my response last time. This +rx_tag_len is
  not needed here and infact it is '0' in case of v1.
  So no effect.
> <snip>
>
>>>>
>>>> -       qup_i2c_issue_read(qup, msg);
>>>> +               qup_i2c_issue_read(qup, msg);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> +               if (ret)
>>>> +                       goto err;
>>>>
>>>> -       do {
>>>>                   left = wait_for_completion_timeout(&qup->xfer, HZ);
>>>>                   if (!left) {
>>>>                           writel(1, qup->base + QUP_SW_RESET);
>>>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>                   }
>>>>
>>>>                   qup_i2c_read_fifo(qup, msg);
>>>> -       } while (qup->pos < msg->len);
>>>> +               qup->blk.block_pos++;
>>>
>>> This should not be incremented, unless we really have read this block.
>>>
>>     We are reading it and only then incrementing it.
>
> But read FIFO function could exit because of timeout, which is
> not checked. The same is true for write operations.
>
> Somehow this patch looks overly complex, I don't believe
> that it should be.
>
> Ivan.
>
>
ok, the read and write fifo timing out error checks should be
  corrected once i check the error code for qup_i2c_wait_ready
  function.

I will split this patch in to couple of smaller patches and make
  sure it does not look complex.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-15 14:44             ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-15 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ivan,

   Sorry resending again, because wrapping seemed to be
   somehow wrong in my previous response.

On 04/15/2015 02:19 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 12:09 +0530, Sricharan R wrote:
>
>>>> +/* frequency definitions for high speed and max speed */
>>>> +#define I2C_QUP_CLK_FAST_FREQ          1000000
>>>
>>> This is fast mode, if I am not mistaken.
>>>
>>    ya, up to 1MHZ is fast and up to 3.4MHZ is HS.
>>    We use this macro to check if the desired freq is in HS range.
>>    The above comment can be changed though to make it clear.
>
> My point was that this is neither high nor max speed.
>
I see that QUP specs defines up to 1MHZ as fast+ speed.
>>>> +
>>>>    /* Status, Error flags */
>>>>    #define I2C_STATUS_WR_BUFFER_FULL      BIT(0)
>>>>    #define I2C_STATUS_BUS_ACTIVE          BIT(8)
>>>> @@ -102,6 +119,15 @@
>>>>    #define RESET_BIT                      0x0
>>>>    #define ONE_BYTE                       0x1
>>>>
>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>
>>> Could you explain what is this for?
>>>
>>     This is a new feature in the V2 version of the controller,
>>     to support multiple i2c sub transfers without having
>>     a 'stop' bit in-between. Without this the i2c controller
>>     inserts a 'stop' on the bus when the WR/RD count registers
>>     reaches zero and are configured for the next transfer. So setting
>>     this bit when the controller is in 'RUN' state, avoids sending the
>>     'stop' during RUN state.
>>     I can add this comment in the patch.
>
> And how v2 of this patch was worked if you introduce this bit now?
> Bit is also not used by downstream driver, AFICS?
>
The one of the reason for this and the bam support patches in
this series was to support multiple transfers of i2c_msgs without
  a 'stop' inbetween them. So without that the driver sends a 'stop'
between each sub-transfer. The v2 of this series supported that only in
bam mode and not in non-bam mode. That was a bug. I saw the difference
in behavior between bam and non-bam mode while testing with a hdmi adv
bridge recently. So added the support in this series. This was neede to
bringup the HDMI adv bridge device. I could have added it as a
  new patch to make it more explicit.

>>
>>>> +
>>>> +struct qup_i2c_block {
>>>> +       int     blocks;
>
> count
>
>>>> +       u8      *block_tag_len;
>
> just tag_len,
>
>>>> +       int     *block_data_len;
>
> just data_len,
>
>>>> +       int     block_pos;
>
> just pos?
>
>>>> +};
>>>> +
>>>>    struct qup_i2c_dev {
>>>>           struct device*dev;
>>>>           void __iomem*base;
>>>> @@ -115,9 +141,17 @@ struct qup_i2c_dev {
>>>>           int     in_fifo_sz;
>>>>           int     out_blk_sz;
>>>>           int     in_blk_sz;
>>>> -
>>>> +       struct  qup_i2c_blockblk;
>>>>           unsigned longone_byte_t;
>>>>
>>>> +       int     is_hs;
>>>> +       bool    use_v2_tags;
>>>> +
>>>> +       int     tx_tag_len;
>>>> +       int     rx_tag_len;
>>>> +       u8      *tags;
>>>> +       int     tags_pos;
>>>> +
>>>>           struct i2c_msg*msg;
>>>>           /* Current posion in user message buffer */
>>>>           int     pos;
>>>> @@ -263,10 +297,19 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>>>>           }
>>>>    }
>>>
>>> Is this better tag related fields grouping?
>>>
>>
>>> struct qup_i2c_tag_block {
>>>
>>>           u8      tag[2];
>>>           // int  tag_len; this is alway 2, or?
>>>           int     data_len; // this could be zero, right?
>>> };
>>>
>> There is a struct for qup_i2c_block which has tag and data len. Not sure
>> what change you suggest above ? Also with V2 transfers tag len need
>>    not be 2. It can be more than that based on the data len.
>
> The point is that: I will like to see better grouping of
> related variables. Now they are spread all over. Would it
> be possible to also take care for tx_tag_len, rx_tag_len,
> tags, tags_pos.
>
For this and the above, i will change the groupings and split this patch
  in to couple of smaller ones.
>>
>>>> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                       int run)
>>>
>>> And 'run' stands for?
>>    'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>     I can change it to is_run_st to make it clear.
>>>>    {
>>>> -       /* Number of entries to shift out, including the start */
>>>> -       int total = msg->len + 1;
>>>> +       /* Total Number of entries to shift out, including the tags */
>>>> +       int total;
>>>> +
>>>> +       if (qup->use_v2_tags) {
>>>> +               total = msg->len + qup->tx_tag_len;
>>>> +               if (run)
>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>
>>> What?
>>>
>>        This means, if the controller is in 'RUN' state, for
>>        reconfiguring the RD/WR counts this bit has to be set to avoid
>>        'stop' bits.
>
> I don't buy it, sorry. Problem with v1 of the tags is that controller
> can not read more than 256 bytes without automatically generate STOP
> at the end, because transfer length specified with QUP_TAG_REC tag
> is 8 bits wide. There is no limitation for writes with v1 tags,
> because controller is explicitly instructed when to send out STOP.
>
correct till this.

> For v2 of the tags, writes behaves more or less the same, and the
> good news are that there is new read tag QUP_TAG_V2_DATARD, which
> did't generate STOP when specified amount of data is read, still
> up to 256 bytes in chunk. Read transfers with size more than 256
> could be formed in following way:
>
> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>
  The above is true for a single subtransfer for reading/writing
more than > 256 bytes. But for doing WRITE, READ kind of sub
  transfers once the first sub transfer (write) is over, and
  while re-configuring the _COUNT registers for the next transfers,
'a stop' between is inserted.
To avoid this,the MX_CONFIG_DURING_RUN  bit should be set while in
  'RUN' state, before re-configuring for the next sub transfer.
  The qupspec calls this as bus 'lock-unlock' feature.

I tested this and it fixed the wrong data reads in the case of the hdmi
adv bridge reads. It was doing 2 i2c_msgs transfers for each i2c_xfer
call.  The data read was wrong without this patch in v1 mode (default)
and even in v2 mode without the lock-unlock even though we do not send
a 'STOP' tag command between sub-transfers.

>>
>>>>
>>>> -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
>>>> +                                               struct i2c_msg *msg, int last)
>>>> +{
>>>> +       u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
>>>> +       int len = 0, prev_len = 0;
>>>> +       int blocks = 0;
>>>> +       int rem;
>>>> +       int block_len = 0;
>>>> +       int data_len;
>>>> +
>>>> +       qup->blk.block_pos = 0;
>>>> +       qup->pos = 0;
>>>> +       qup->blk.blocks = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
>>>> +       rem = msg->len % QUP_READ_LIMIT;
>>>> +
>>>> +       /* 2 tag bytes for each block + 2 extra bytes for first block */
>>>> +       qup->tags = kzalloc((qup->blk.blocks * 2) + 2, GFP_KERNEL);
>>>> +       qup->blk.block_tag_len = kzalloc(qup->blk.blocks, GFP_KERNEL);
>>>> +       qup->blk.block_data_len = kzalloc(sizeof(*qup->blk.block_data_len) *
>>>> +                                               qup->blk.blocks, GFP_KERNEL);
>>>
>>> Whouldn't be easy to kcalloc struct qup_i2c_tag_block?
>>>
>>>
>>> Allocations could fail and memory is leaking here.
>>>
>>    ya correct, will change this. Freeing is done at the end of xfer
>>    function, but will have to check for allocation failure.
>
> Do you see how memory leak here?
>
if the first allocation pass and second one fails, and i will have
to move the kfree calls at the end of i2c_xfer inside the loop.
>>
>>>> +
>>>> +       while (blocks < qup->blk.blocks) {
>>>>
>>>> +               blocks++;
>>>
>>> Looks like 'for' cycle to me.
>>>
>>    sorry, not getting it ?
>
> This 'while' loop is old plain 'for'.
>
ok
>>>> +       }
>>>> +
>>>> +       qup->tx_tag_len = len;
>>>> +
>>>> +       if (msg->flags & I2C_M_RD)
>>>> +               qup->rx_tag_len = (qup->blk.blocks * 2);
>
> This will need some explanation.
>
ok, will add it.

>
>>>> +
>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +{
>>>> +       u32 data_len = 0, tag_len;
>>>> +
>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>> +
>>>> +       if (!(msg->flags & I2C_M_RD))
>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>> +
>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>
>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>> are completely written to FIFO buffer, right?
>>>
>>    Yes, since we send/read data in blocks (256 bytes).
>
> How deep is the FIFO? Is it guaranteed that "the whole" write
> or read data, including tags will fit in.
>
  Write/read fifo functions (also for V1) currently wait for the
   fifo full and empty flags conditions. This will ensure that the
  fifo full and empty conditions are taken care before writing
  and reading. But this can be improved by waiting for
  block_write/read flags to improve the throughput.

>>>>
>>>> +
>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>> +                                                               int run, int last)
>>>>    {
>>>>           unsigned long left;
>>>>           int ret;
>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>           qup->msg = msg;
>>>>           qup->pos = 0;
>>>>
>>>> +       if (qup->use_v2_tags)
>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>> +       else
>>>> +               qup->blk.blocks = 0;
>>>> +
>>>>           enable_irq(qup->irq);
>>>>
>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +       if (!run) {
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>
>>> To run away, or not?
>>>
>>     Means, if the controller is not in RUN state, put it in to 'RUN'
>>     state.
>
> And what is the problem if controller is put in PAUSED state, FIFO
> filled with data and then RUN again, like in v2 of this patch?
>
  This function is not entered with controller in PAUSED state
  Only in Reset state (for the first transfer) and Run state for
  the subsequent sub-transfers. The reason for having this 'run'
  variable was that while using the lock-unlock feature, the
  controller should not be put in to run-reset-run state
  in-between transfers.

> <snip>
>
>>>>
>>>> -static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>> +static void qup_i2c_read_fifo_v1(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>    {
>>>> -       u32 opflags;
>>>>           u32 val = 0;
>>>>           int idx;
>>>> +       int len = msg->len + qup->rx_tag_len;
>>>
>>> Is this intentional?
>>>
>>      Yes, since i changed the loop around qup_i2c_read_one to count for
>>      blocks.
>
> No, this doesn't make any sense. v1 tags didn't use rx_tag_len, and
> I don't see how this is related to counting blocks, in this function.
>
  sorry. Did confuse my response last time. This +rx_tag_len is
  not needed here and infact it is '0' in case of v1.
  So no effect.
> <snip>
>
>>>>
>>>> -       qup_i2c_issue_read(qup, msg);
>>>> +               qup_i2c_issue_read(qup, msg);
>>>>
>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> -       if (ret)
>>>> -               goto err;
>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>> +               if (ret)
>>>> +                       goto err;
>>>>
>>>> -       do {
>>>>                   left = wait_for_completion_timeout(&qup->xfer, HZ);
>>>>                   if (!left) {
>>>>                           writel(1, qup->base + QUP_SW_RESET);
>>>> @@ -481,7 +726,8 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>                   }
>>>>
>>>>                   qup_i2c_read_fifo(qup, msg);
>>>> -       } while (qup->pos < msg->len);
>>>> +               qup->blk.block_pos++;
>>>
>>> This should not be incremented, unless we really have read this block.
>>>
>>     We are reading it and only then incrementing it.
>
> But read FIFO function could exit because of timeout, which is
> not checked. The same is true for write operations.
>
> Somehow this patch looks overly complex, I don't believe
> that it should be.
>
> Ivan.
>
>
ok, the read and write fifo timing out error checks should be
  corrected once i check the error code for qup_i2c_wait_ready
  function.

I will split this patch in to couple of smaller patches and make
  sure it does not look complex.

Regards,
  Sricharan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-15 14:44             ` Sricharan R
  (?)
@ 2015-04-16  8:36                 ` Ivan T. Ivanov
  -1 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-16  8:36 UTC (permalink / raw)
  To: Sricharan R
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	galak-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, agross-sgV2jX0FEOL9JmXXK+q4OQ,
	dmaengine-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r


Hi Sricharan,

On Wed, 2015-04-15 at 20:14 +0530, Sricharan R wrote:
> 
> > > > > 
> > > > > +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
> > > > 
> > > > Could you explain what is this for?
> > > > 
> > >     This is a new feature in the V2 version of the controller,
> > >     to support multiple i2c sub transfers without having
> > >     a 'stop' bit in-between. Without this the i2c controller
> > >     inserts a 'stop' on the bus when the WR/RD count registers
> > >     reaches zero and are configured for the next transfer. So setting
> > >     this bit when the controller is in 'RUN' state, avoids sending the
> > >     'stop' during RUN state.
> > >     I can add this comment in the patch.
> > 
> > And how v2 of this patch was worked if you introduce this bit now?
> > Bit is also not used by downstream driver, AFICS?
> > 
> The one of the reason for this and the bam support patches in
> this series was to support multiple transfers of i2c_msgs without
>   a 'stop' inbetween them. So without that the driver sends a 'stop'
> between each sub-transfer. 

Are you saying that there is bug in the hardware? Please, could you
point me to codeaurora driver, which is using this bit? 



-static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                       int run)
> > > > 
> > > > And 'run' stands for?
> > >    'run' just says whether the controller is in 'RUN' or 'RESET' state.
> > >     I can change it to is_run_st to make it clear.
> > > > >    {
> > > > > -       /* Number of entries to shift out, including the start */
> > > > > -       int total = msg->len + 1;
> > > > > +       /* Total Number of entries to shift out, including the tags */
> > > > > +       int total;
> > > > > +
> > > > > +       if (qup->use_v2_tags) {
> > > > > +               total = msg->len + qup->tx_tag_len;
> > > > > +               if (run)
> > > > > +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
> > > > 
> > > > What?
> > > > 
> > >        This means, if the controller is in 'RUN' state, for
> > >        reconfiguring the RD/WR counts this bit has to be set to avoid
> > >        'stop' bits.
> > 
> > I don't buy it, sorry. Problem with v1 of the tags is that controller
> > can not read more than 256 bytes without automatically generate STOP
> > at the end, because transfer length specified with QUP_TAG_REC tag
> > is 8 bits wide. There is no limitation for writes with v1 tags,
> > because controller is explicitly instructed when to send out STOP.
> > 
> correct till this.
> 
> > For v2 of the tags, writes behaves more or less the same, and the
> > good news are that there is new read tag QUP_TAG_V2_DATARD, which
> > did't generate STOP when specified amount of data is read, still
> > up to 256 bytes in chunk. Read transfers with size more than 256
> > could be formed in following way:
> > 
> > V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
> > 
>   The above is true for a single subtransfer for reading/writing
> more than > 256 bytes. But for doing WRITE, READ kind of sub
>   transfers once the first sub transfer (write) is over, and
>   while re-configuring the _COUNT registers for the next transfers,
> 'a stop' between is inserted.

>From controller itself or driver?

> > > > > +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +{
> > > > > +       u32 data_len = 0, tag_len;
> > > > > +
> > > > > +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> > > > > +
> > > > > +       if (!(msg->flags & I2C_M_RD))
> > > > > +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> > > > > +
> > > > > +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
> > > > 
> > > > This assumes that writes are up to 256 bytes, and tags and data blocks
> > > > are completely written to FIFO buffer, right?
> > > > 
> > >    Yes, since we send/read data in blocks (256 bytes).
> > 
> > How deep is the FIFO? Is it guaranteed that "the whole" write
> > or read data, including tags will fit in.
> > 
>   Write/read fifo functions (also for V1) currently wait for the
>    fifo full and empty flags conditions.

I will say that this is true for v1, but not for v2, 
because the way of how FIFO is filled in v2.

> > > > > +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                               int run, int last)
> > > > >    {
> > > > >           unsigned long left;
> > > > >           int ret;
> > > > > @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct 
> > > > > i2c_msg *msg)
> > > > >           qup->msg = msg;
> > > > >           qup->pos = 0;
> > > > > 
> > > > > +       if (qup->use_v2_tags)
> > > > > +               qup_i2c_create_tag_v2(qup, msg, last);
> > > > > +       else
> > > > > +               qup->blk.blocks = 0;
> > > > > +
> > > > >           enable_irq(qup->irq);
> > > > > 
> > > > > -       qup_i2c_set_write_mode(qup, msg);
> > > > > +       qup_i2c_set_write_mode(qup, msg, run);
> > > > > 
> > > > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > > -       if (ret)
> > > > > -               goto err;
> > > > > +       if (!run) {
> > > > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > 
> > > > To run away, or not?
> > > > 
> > >     Means, if the controller is not in RUN state, put it in to 'RUN'
> > >     state.
> > 
> > And what is the problem if controller is put in PAUSED state, FIFO
> > filled with data and then RUN again, like in v2 of this patch?
> > 
>   This function is not entered with controller in PAUSED state
>   Only in Reset state (for the first transfer) and Run state for
>   the subsequent sub-transfers. The reason for having this 'run'
>   variable was that while using the lock-unlock feature, the
>   controller should not be put in to run-reset-run state
>   in-between transfers.

Lets see how it will look, when new qup_i2c_write_one_v2 is introduced :-)

Ivan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-16  8:36                 ` Ivan T. Ivanov
  0 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-16  8:36 UTC (permalink / raw)
  To: Sricharan R
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel


Hi Sricharan,

On Wed, 2015-04-15 at 20:14 +0530, Sricharan R wrote:
> 
> > > > > 
> > > > > +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
> > > > 
> > > > Could you explain what is this for?
> > > > 
> > >     This is a new feature in the V2 version of the controller,
> > >     to support multiple i2c sub transfers without having
> > >     a 'stop' bit in-between. Without this the i2c controller
> > >     inserts a 'stop' on the bus when the WR/RD count registers
> > >     reaches zero and are configured for the next transfer. So setting
> > >     this bit when the controller is in 'RUN' state, avoids sending the
> > >     'stop' during RUN state.
> > >     I can add this comment in the patch.
> > 
> > And how v2 of this patch was worked if you introduce this bit now?
> > Bit is also not used by downstream driver, AFICS?
> > 
> The one of the reason for this and the bam support patches in
> this series was to support multiple transfers of i2c_msgs without
>   a 'stop' inbetween them. So without that the driver sends a 'stop'
> between each sub-transfer. 

Are you saying that there is bug in the hardware? Please, could you
point me to codeaurora driver, which is using this bit? 



-static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                       int run)
> > > > 
> > > > And 'run' stands for?
> > >    'run' just says whether the controller is in 'RUN' or 'RESET' state.
> > >     I can change it to is_run_st to make it clear.
> > > > >    {
> > > > > -       /* Number of entries to shift out, including the start */
> > > > > -       int total = msg->len + 1;
> > > > > +       /* Total Number of entries to shift out, including the tags */
> > > > > +       int total;
> > > > > +
> > > > > +       if (qup->use_v2_tags) {
> > > > > +               total = msg->len + qup->tx_tag_len;
> > > > > +               if (run)
> > > > > +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
> > > > 
> > > > What?
> > > > 
> > >        This means, if the controller is in 'RUN' state, for
> > >        reconfiguring the RD/WR counts this bit has to be set to avoid
> > >        'stop' bits.
> > 
> > I don't buy it, sorry. Problem with v1 of the tags is that controller
> > can not read more than 256 bytes without automatically generate STOP
> > at the end, because transfer length specified with QUP_TAG_REC tag
> > is 8 bits wide. There is no limitation for writes with v1 tags,
> > because controller is explicitly instructed when to send out STOP.
> > 
> correct till this.
> 
> > For v2 of the tags, writes behaves more or less the same, and the
> > good news are that there is new read tag QUP_TAG_V2_DATARD, which
> > did't generate STOP when specified amount of data is read, still
> > up to 256 bytes in chunk. Read transfers with size more than 256
> > could be formed in following way:
> > 
> > V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
> > 
>   The above is true for a single subtransfer for reading/writing
> more than > 256 bytes. But for doing WRITE, READ kind of sub
>   transfers once the first sub transfer (write) is over, and
>   while re-configuring the _COUNT registers for the next transfers,
> 'a stop' between is inserted.

>From controller itself or driver?

> > > > > +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +{
> > > > > +       u32 data_len = 0, tag_len;
> > > > > +
> > > > > +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> > > > > +
> > > > > +       if (!(msg->flags & I2C_M_RD))
> > > > > +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> > > > > +
> > > > > +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
> > > > 
> > > > This assumes that writes are up to 256 bytes, and tags and data blocks
> > > > are completely written to FIFO buffer, right?
> > > > 
> > >    Yes, since we send/read data in blocks (256 bytes).
> > 
> > How deep is the FIFO? Is it guaranteed that "the whole" write
> > or read data, including tags will fit in.
> > 
>   Write/read fifo functions (also for V1) currently wait for the
>    fifo full and empty flags conditions.

I will say that this is true for v1, but not for v2, 
because the way of how FIFO is filled in v2.

> > > > > +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                               int run, int last)
> > > > >    {
> > > > >           unsigned long left;
> > > > >           int ret;
> > > > > @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct 
> > > > > i2c_msg *msg)
> > > > >           qup->msg = msg;
> > > > >           qup->pos = 0;
> > > > > 
> > > > > +       if (qup->use_v2_tags)
> > > > > +               qup_i2c_create_tag_v2(qup, msg, last);
> > > > > +       else
> > > > > +               qup->blk.blocks = 0;
> > > > > +
> > > > >           enable_irq(qup->irq);
> > > > > 
> > > > > -       qup_i2c_set_write_mode(qup, msg);
> > > > > +       qup_i2c_set_write_mode(qup, msg, run);
> > > > > 
> > > > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > > -       if (ret)
> > > > > -               goto err;
> > > > > +       if (!run) {
> > > > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > 
> > > > To run away, or not?
> > > > 
> > >     Means, if the controller is not in RUN state, put it in to 'RUN'
> > >     state.
> > 
> > And what is the problem if controller is put in PAUSED state, FIFO
> > filled with data and then RUN again, like in v2 of this patch?
> > 
>   This function is not entered with controller in PAUSED state
>   Only in Reset state (for the first transfer) and Run state for
>   the subsequent sub-transfers. The reason for having this 'run'
>   variable was that while using the lock-unlock feature, the
>   controller should not be put in to run-reset-run state
>   in-between transfers.

Lets see how it will look, when new qup_i2c_write_one_v2 is introduced :-)

Ivan


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-16  8:36                 ` Ivan T. Ivanov
  0 siblings, 0 replies; 41+ messages in thread
From: Ivan T. Ivanov @ 2015-04-16  8:36 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Sricharan,

On Wed, 2015-04-15 at 20:14 +0530, Sricharan R wrote:
> 
> > > > > 
> > > > > +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
> > > > 
> > > > Could you explain what is this for?
> > > > 
> > >     This is a new feature in the V2 version of the controller,
> > >     to support multiple i2c sub transfers without having
> > >     a 'stop' bit in-between. Without this the i2c controller
> > >     inserts a 'stop' on the bus when the WR/RD count registers
> > >     reaches zero and are configured for the next transfer. So setting
> > >     this bit when the controller is in 'RUN' state, avoids sending the
> > >     'stop' during RUN state.
> > >     I can add this comment in the patch.
> > 
> > And how v2 of this patch was worked if you introduce this bit now?
> > Bit is also not used by downstream driver, AFICS?
> > 
> The one of the reason for this and the bam support patches in
> this series was to support multiple transfers of i2c_msgs without
>   a 'stop' inbetween them. So without that the driver sends a 'stop'
> between each sub-transfer. 

Are you saying that there is bug in the hardware? Please, could you
point me to codeaurora driver, which is using this bit? 



-static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                       int run)
> > > > 
> > > > And 'run' stands for?
> > >    'run' just says whether the controller is in 'RUN' or 'RESET' state.
> > >     I can change it to is_run_st to make it clear.
> > > > >    {
> > > > > -       /* Number of entries to shift out, including the start */
> > > > > -       int total = msg->len + 1;
> > > > > +       /* Total Number of entries to shift out, including the tags */
> > > > > +       int total;
> > > > > +
> > > > > +       if (qup->use_v2_tags) {
> > > > > +               total = msg->len + qup->tx_tag_len;
> > > > > +               if (run)
> > > > > +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
> > > > 
> > > > What?
> > > > 
> > >        This means, if the controller is in 'RUN' state, for
> > >        reconfiguring the RD/WR counts this bit has to be set to avoid
> > >        'stop' bits.
> > 
> > I don't buy it, sorry. Problem with v1 of the tags is that controller
> > can not read more than 256 bytes without automatically generate STOP
> > at the end, because transfer length specified with QUP_TAG_REC tag
> > is 8 bits wide. There is no limitation for writes with v1 tags,
> > because controller is explicitly instructed when to send out STOP.
> > 
> correct till this.
> 
> > For v2 of the tags, writes behaves more or less the same, and the
> > good news are that there is new read tag QUP_TAG_V2_DATARD, which
> > did't generate STOP when specified amount of data is read, still
> > up to 256 bytes in chunk. Read transfers with size more than 256
> > could be formed in following way:
> > 
> > V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
> > 
>   The above is true for a single subtransfer for reading/writing
> more than > 256 bytes. But for doing WRITE, READ kind of sub
>   transfers once the first sub transfer (write) is over, and
>   while re-configuring the _COUNT registers for the next transfers,
> 'a stop' between is inserted.

>From controller itself or driver?

> > > > > +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> > > > > +{
> > > > > +       u32 data_len = 0, tag_len;
> > > > > +
> > > > > +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
> > > > > +
> > > > > +       if (!(msg->flags & I2C_M_RD))
> > > > > +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
> > > > > +
> > > > > +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
> > > > 
> > > > This assumes that writes are up to 256 bytes, and tags and data blocks
> > > > are completely written to FIFO buffer, right?
> > > > 
> > >    Yes, since we send/read data in blocks (256 bytes).
> > 
> > How deep is the FIFO? Is it guaranteed that "the whole" write
> > or read data, including tags will fit in.
> > 
>   Write/read fifo functions (also for V1) currently wait for the
>    fifo full and empty flags conditions.

I will say that this is true for v1, but not for v2, 
because the way of how FIFO is filled in v2.

> > > > > +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
> > > > > +                                                               int run, int last)
> > > > >    {
> > > > >           unsigned long left;
> > > > >           int ret;
> > > > > @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct 
> > > > > i2c_msg *msg)
> > > > >           qup->msg = msg;
> > > > >           qup->pos = 0;
> > > > > 
> > > > > +       if (qup->use_v2_tags)
> > > > > +               qup_i2c_create_tag_v2(qup, msg, last);
> > > > > +       else
> > > > > +               qup->blk.blocks = 0;
> > > > > +
> > > > >           enable_irq(qup->irq);
> > > > > 
> > > > > -       qup_i2c_set_write_mode(qup, msg);
> > > > > +       qup_i2c_set_write_mode(qup, msg, run);
> > > > > 
> > > > > -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > > -       if (ret)
> > > > > -               goto err;
> > > > > +       if (!run) {
> > > > > +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
> > > > 
> > > > To run away, or not?
> > > > 
> > >     Means, if the controller is not in RUN state, put it in to 'RUN'
> > >     state.
> > 
> > And what is the problem if controller is put in PAUSED state, FIFO
> > filled with data and then RUN again, like in v2 of this patch?
> > 
>   This function is not entered with controller in PAUSED state
>   Only in Reset state (for the first transfer) and Run state for
>   the subsequent sub-transfers. The reason for having this 'run'
>   variable was that while using the lock-unlock feature, the
>   controller should not be put in to run-reset-run state
>   in-between transfers.

Lets see how it will look, when new qup_i2c_write_one_v2 is introduced :-)

Ivan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support
  2015-04-16  8:36                 ` Ivan T. Ivanov
@ 2015-04-16  9:39                   ` Sricharan R
  -1 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-16  9:39 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: devicetree, linux-arm-msm, galak, linux-kernel, linux-i2c,
	agross, dmaengine, linux-arm-kernel

Hi Ivan,

On 04/16/2015 02:06 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 20:14 +0530, Sricharan R wrote:
>>
>>>>>>
>>>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>>>
>>>>> Could you explain what is this for?
>>>>>
>>>>      This is a new feature in the V2 version of the controller,
>>>>      to support multiple i2c sub transfers without having
>>>>      a 'stop' bit in-between. Without this the i2c controller
>>>>      inserts a 'stop' on the bus when the WR/RD count registers
>>>>      reaches zero and are configured for the next transfer. So setting
>>>>      this bit when the controller is in 'RUN' state, avoids sending the
>>>>      'stop' during RUN state.
>>>>      I can add this comment in the patch.
>>>
>>> And how v2 of this patch was worked if you introduce this bit now?
>>> Bit is also not used by downstream driver, AFICS?
>>>
>> The one of the reason for this and the bam support patches in
>> this series was to support multiple transfers of i2c_msgs without
>>    a 'stop' inbetween them. So without that the driver sends a 'stop'
>> between each sub-transfer.
>
> Are you saying that there is bug in the hardware? Please, could you
> point me to codeaurora driver, which is using this bit?
>
   The controller was not supporting this 'no-stop' feature by default
   and not sure whether to call it a 'bug' or 'missing feature', which
   it supports now anyway. Regarding the internal driver, it was
   trying to coalesce the writes (if they are to same address) by
   configuring the WR_CNT register to the sum of msg->len of the
   consecutive sub-transfers. This is no more needed with this 'feature'.
>
>
> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>>>> +                                                       int run)
>>>>>
>>>>> And 'run' stands for?
>>>>     'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>>>      I can change it to is_run_st to make it clear.
>>>>>>     {
>>>>>> -       /* Number of entries to shift out, including the start */
>>>>>> -       int total = msg->len + 1;
>>>>>> +       /* Total Number of entries to shift out, including the tags */
>>>>>> +       int total;
>>>>>> +
>>>>>> +       if (qup->use_v2_tags) {
>>>>>> +               total = msg->len + qup->tx_tag_len;
>>>>>> +               if (run)
>>>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>>>
>>>>> What?
>>>>>
>>>>         This means, if the controller is in 'RUN' state, for
>>>>         reconfiguring the RD/WR counts this bit has to be set to avoid
>>>>         'stop' bits.
>>>
>>> I don't buy it, sorry. Problem with v1 of the tags is that controller
>>> can not read more than 256 bytes without automatically generate STOP
>>> at the end, because transfer length specified with QUP_TAG_REC tag
>>> is 8 bits wide. There is no limitation for writes with v1 tags,
>>> because controller is explicitly instructed when to send out STOP.
>>>
>> correct till this.
>>
>>> For v2 of the tags, writes behaves more or less the same, and the
>>> good news are that there is new read tag QUP_TAG_V2_DATARD, which
>>> did't generate STOP when specified amount of data is read, still
>>> up to 256 bytes in chunk. Read transfers with size more than 256
>>> could be formed in following way:
>>>
>>> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>>>
>>    The above is true for a single subtransfer for reading/writing
>> more than > 256 bytes. But for doing WRITE, READ kind of sub
>>    transfers once the first sub transfer (write) is over, and
>>    while re-configuring the _COUNT registers for the next transfers,
>> 'a stop' between is inserted.
>
>  From controller itself or driver?
>
  controller itself.

>>>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>>> +{
>>>>>> +       u32 data_len = 0, tag_len;
>>>>>> +
>>>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>>>> +
>>>>>> +       if (!(msg->flags & I2C_M_RD))
>>>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>>>> +
>>>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>>>
>>>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>>>> are completely written to FIFO buffer, right?
>>>>>
>>>>     Yes, since we send/read data in blocks (256 bytes).
>>>
>>> How deep is the FIFO? Is it guaranteed that "the whole" write
>>> or read data, including tags will fit in.
>>>
>>    Write/read fifo functions (also for V1) currently wait for the
>>     fifo full and empty flags conditions.
>
> I will say that this is true for v1, but not for v2,
> because the way of how FIFO is filled in v2.
>
   fifo is filled using the same 'flags' in both v1 and v2.
   The difference is the way tags and data are assembled in the
   output. But as i said, it can be improved atleast in v2 easily
   (can be done in v1 also, but is not something required in this
   patch) and i will change that in next version.

>>>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>>>> +                                                               int run, int last)
>>>>>>     {
>>>>>>            unsigned long left;
>>>>>>            int ret;
>>>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct
>>>>>> i2c_msg *msg)
>>>>>>            qup->msg = msg;
>>>>>>            qup->pos = 0;
>>>>>>
>>>>>> +       if (qup->use_v2_tags)
>>>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>>>> +       else
>>>>>> +               qup->blk.blocks = 0;
>>>>>> +
>>>>>>            enable_irq(qup->irq);
>>>>>>
>>>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>>>
>>>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>>>> -       if (ret)
>>>>>> -               goto err;
>>>>>> +       if (!run) {
>>>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>>>
>>>>> To run away, or not?
>>>>>
>>>>      Means, if the controller is not in RUN state, put it in to 'RUN'
>>>>      state.
>>>
>>> And what is the problem if controller is put in PAUSED state, FIFO
>>> filled with data and then RUN again, like in v2 of this patch?
>>>
>>    This function is not entered with controller in PAUSED state
>>    Only in Reset state (for the first transfer) and Run state for
>>    the subsequent sub-transfers. The reason for having this 'run'
>>    variable was that while using the lock-unlock feature, the
>>    controller should not be put in to run-reset-run state
>>    in-between transfers.
>
> Lets see how it will look, when new qup_i2c_write_one_v2 is introduced :-)
>
ok.

Regards,
  Sricharan
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH V3 2/6] i2c: qup: Add V2 tags support
@ 2015-04-16  9:39                   ` Sricharan R
  0 siblings, 0 replies; 41+ messages in thread
From: Sricharan R @ 2015-04-16  9:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ivan,

On 04/16/2015 02:06 PM, Ivan T. Ivanov wrote:
>
> Hi Sricharan,
>
> On Wed, 2015-04-15 at 20:14 +0530, Sricharan R wrote:
>>
>>>>>>
>>>>>> +#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
>>>>>
>>>>> Could you explain what is this for?
>>>>>
>>>>      This is a new feature in the V2 version of the controller,
>>>>      to support multiple i2c sub transfers without having
>>>>      a 'stop' bit in-between. Without this the i2c controller
>>>>      inserts a 'stop' on the bus when the WR/RD count registers
>>>>      reaches zero and are configured for the next transfer. So setting
>>>>      this bit when the controller is in 'RUN' state, avoids sending the
>>>>      'stop' during RUN state.
>>>>      I can add this comment in the patch.
>>>
>>> And how v2 of this patch was worked if you introduce this bit now?
>>> Bit is also not used by downstream driver, AFICS?
>>>
>> The one of the reason for this and the bam support patches in
>> this series was to support multiple transfers of i2c_msgs without
>>    a 'stop' inbetween them. So without that the driver sends a 'stop'
>> between each sub-transfer.
>
> Are you saying that there is bug in the hardware? Please, could you
> point me to codeaurora driver, which is using this bit?
>
   The controller was not supporting this 'no-stop' feature by default
   and not sure whether to call it a 'bug' or 'missing feature', which
   it supports now anyway. Regarding the internal driver, it was
   trying to coalesce the writes (if they are to same address) by
   configuring the WR_CNT register to the sum of msg->len of the
   consecutive sub-transfers. This is no more needed with this 'feature'.
>
>
> -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>>> +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>>>> +                                                       int run)
>>>>>
>>>>> And 'run' stands for?
>>>>     'run' just says whether the controller is in 'RUN' or 'RESET' state.
>>>>      I can change it to is_run_st to make it clear.
>>>>>>     {
>>>>>> -       /* Number of entries to shift out, including the start */
>>>>>> -       int total = msg->len + 1;
>>>>>> +       /* Total Number of entries to shift out, including the tags */
>>>>>> +       int total;
>>>>>> +
>>>>>> +       if (qup->use_v2_tags) {
>>>>>> +               total = msg->len + qup->tx_tag_len;
>>>>>> +               if (run)
>>>>>> +                       total |= QUP_I2C_MX_CONFIG_DURING_RUN;
>>>>>
>>>>> What?
>>>>>
>>>>         This means, if the controller is in 'RUN' state, for
>>>>         reconfiguring the RD/WR counts this bit has to be set to avoid
>>>>         'stop' bits.
>>>
>>> I don't buy it, sorry. Problem with v1 of the tags is that controller
>>> can not read more than 256 bytes without automatically generate STOP
>>> at the end, because transfer length specified with QUP_TAG_REC tag
>>> is 8 bits wide. There is no limitation for writes with v1 tags,
>>> because controller is explicitly instructed when to send out STOP.
>>>
>> correct till this.
>>
>>> For v2 of the tags, writes behaves more or less the same, and the
>>> good news are that there is new read tag QUP_TAG_V2_DATARD, which
>>> did't generate STOP when specified amount of data is read, still
>>> up to 256 bytes in chunk. Read transfers with size more than 256
>>> could be formed in following way:
>>>
>>> V2_START | Slave Address | V2_DATARD | countx | ... | V2_DATARD_STOP | county.
>>>
>>    The above is true for a single subtransfer for reading/writing
>> more than > 256 bytes. But for doing WRITE, READ kind of sub
>>    transfers once the first sub transfer (write) is over, and
>>    while re-configuring the _COUNT registers for the next transfers,
>> 'a stop' between is inserted.
>
>  From controller itself or driver?
>
  controller itself.

>>>>>> +static void qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>>> +{
>>>>>> +       u32 data_len = 0, tag_len;
>>>>>> +
>>>>>> +       tag_len = qup->blk.block_tag_len[qup->blk.block_pos];
>>>>>> +
>>>>>> +       if (!(msg->flags & I2C_M_RD))
>>>>>> +               data_len = qup->blk.block_data_len[qup->blk.block_pos];
>>>>>> +
>>>>>> +       qup_i2c_send_data(qup, tag_len, qup->tags, data_len, msg->buf);
>>>>>
>>>>> This assumes that writes are up to 256 bytes, and tags and data blocks
>>>>> are completely written to FIFO buffer, right?
>>>>>
>>>>     Yes, since we send/read data in blocks (256 bytes).
>>>
>>> How deep is the FIFO? Is it guaranteed that "the whole" write
>>> or read data, including tags will fit in.
>>>
>>    Write/read fifo functions (also for V1) currently wait for the
>>     fifo full and empty flags conditions.
>
> I will say that this is true for v1, but not for v2,
> because the way of how FIFO is filled in v2.
>
   fifo is filled using the same 'flags' in both v1 and v2.
   The difference is the way tags and data are assembled in the
   output. But as i said, it can be improved atleast in v2 easily
   (can be done in v1 also, but is not something required in this
   patch) and i will change that in next version.

>>>>>> +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>>>>>> +                                                               int run, int last)
>>>>>>     {
>>>>>>            unsigned long left;
>>>>>>            int ret;
>>>>>> @@ -329,13 +501,20 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct
>>>>>> i2c_msg *msg)
>>>>>>            qup->msg = msg;
>>>>>>            qup->pos = 0;
>>>>>>
>>>>>> +       if (qup->use_v2_tags)
>>>>>> +               qup_i2c_create_tag_v2(qup, msg, last);
>>>>>> +       else
>>>>>> +               qup->blk.blocks = 0;
>>>>>> +
>>>>>>            enable_irq(qup->irq);
>>>>>>
>>>>>> -       qup_i2c_set_write_mode(qup, msg);
>>>>>> +       qup_i2c_set_write_mode(qup, msg, run);
>>>>>>
>>>>>> -       ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>>>> -       if (ret)
>>>>>> -               goto err;
>>>>>> +       if (!run) {
>>>>>> +               ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
>>>>>
>>>>> To run away, or not?
>>>>>
>>>>      Means, if the controller is not in RUN state, put it in to 'RUN'
>>>>      state.
>>>
>>> And what is the problem if controller is put in PAUSED state, FIFO
>>> filled with data and then RUN again, like in v2 of this patch?
>>>
>>    This function is not entered with controller in PAUSED state
>>    Only in Reset state (for the first transfer) and Run state for
>>    the subsequent sub-transfers. The reason for having this 'run'
>>    variable was that while using the lock-unlock feature, the
>>    controller should not be put in to run-reset-run state
>>    in-between transfers.
>
> Lets see how it will look, when new qup_i2c_write_one_v2 is introduced :-)
>
ok.

Regards,
  Sricharan
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2015-04-16  9:39 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-11  7:08 [PATCH V3 0/6] i2c: qup: Add support for v2 tags and bam dma Sricharan R
2015-04-11  7:08 ` Sricharan R
2015-04-11  7:08 ` Sricharan R
2015-04-11  7:09 ` [PATCH V3 2/6] i2c: qup: Add V2 tags support Sricharan R
2015-04-11  7:09   ` Sricharan R
2015-04-14 15:16   ` Ivan T. Ivanov
2015-04-14 15:16     ` Ivan T. Ivanov
     [not found]     ` <1429024595.16939.5.camel-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
2015-04-15  6:39       ` Sricharan R
2015-04-15  6:39         ` Sricharan R
2015-04-15  6:39         ` Sricharan R
2015-04-15  8:49         ` Ivan T. Ivanov
2015-04-15  8:49           ` Ivan T. Ivanov
2015-04-15 13:20           ` Sricharan R
2015-04-15 13:20             ` Sricharan R
2015-04-15 14:44           ` Sricharan R
2015-04-15 14:44             ` Sricharan R
     [not found]             ` <552E7962.40606-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-04-16  8:36               ` Ivan T. Ivanov
2015-04-16  8:36                 ` Ivan T. Ivanov
2015-04-16  8:36                 ` Ivan T. Ivanov
2015-04-16  9:39                 ` Sricharan R
2015-04-16  9:39                   ` Sricharan R
     [not found] ` <1428736145-18361-1-git-send-email-sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-04-11  7:09   ` [PATCH V3 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09   ` [PATCH V3 3/6] i2c: qup: Add bam dma capabilities Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09   ` [PATCH V3 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09   ` [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node Sricharan R
2015-04-11  7:09     ` Sricharan R
2015-04-11  7:09     ` Sricharan R
     [not found]     ` <1428736145-18361-6-git-send-email-sricharan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-04-11 22:12       ` Sergei Shtylyov
2015-04-11 22:12         ` Sergei Shtylyov
2015-04-11 22:12         ` Sergei Shtylyov
     [not found]         ` <55299C4A.3020905-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
2015-04-13  4:14           ` Sricharan R
2015-04-13  4:14             ` Sricharan R
2015-04-13  4:14             ` Sricharan R
2015-04-11  7:09 ` [PATCH V3 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node Sricharan R
2015-04-11  7:09   ` Sricharan R

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.