[PATCH V5 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts

2015-11-17 Thread Sricharan R
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 other places as well.

Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 67 +++-
 1 file changed, 48 insertions(+), 19 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index fdcbdab..81ed120 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_BIT0x1
+#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);
}
 }
 
@@ -261,13 +280,13 @@ 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 int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
u32 addr = msg->addr << 1;
u32 qup_tag;
-   u32 opflags;
int idx;
u32 val;
+   int ret = 0;
 
if (qup->pos == 0) {
val = QUP_TAG_START | addr;
@@ -279,9 +298,10 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
 
while (qup->pos < msg->len) {
/* Check that there's space in the FIFO for our pair */
-   opflags = readl(qup->base + QUP_OPERATIONAL);
-   if (opflags & QUP_OUT_FULL)
-   break;
+   ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL, RESET_BIT,
+4 * ONE_BYTE);
+   if (ret)
+   return ret;
 
if (qup->pos == msg->len - 1)
qup_tag = QUP_TAG_STOP;
@@ -300,6 +320,8 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
qup->pos++;
idx++;
}
+
+   return ret;
 }
 
 static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
@@ -325,7 +347,9 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
if (ret)
goto err;
 
-   qup_i2c_issue_write(qup, msg);
+   ret = qup_i2c_issue_write(qup, msg);
+   if (ret)
+   goto err;
 
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
@@ -347,7 +371,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);
@@ -384,18 +408,19 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
 }
 
 
-static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int qup_i2c_

[PATCH V5 0/6] i2c: qup: Add support for v2 tags and bam dma

2015-11-17 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of i2c command tags.
Tag codes instructs the controller to perform a operation like read/write.
This new tagging version supports 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.

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

[V5] Addressed few more comments from Ivan T. Ivanov.
 Squashed patch 2 and 3 as no point in having only few lines of
 common code between v1 and v2 tags for increased complexity.
 Couple of non functional review comments fixes in patch 3, 4.
 Added a change in patch 4 to have proper transfer completion in
 a corner case. patch 5, 6 unchanged.

[V4] Added a patch to factor out some common code.
 Removed support for freq > 400KHZ as per comments.
 Addressed comments from Ivan T. Ivanov to keep the code for
 V2 support in a separate path. 
 Changed the authorship of V2 tags support patch.

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

 http://comments.gmane.org/gmane.linux.drivers.i2c/22497

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

Sricharan R (6):
  i2c: qup: Change qup_wait_writeready function to use for all timeouts
  i2c: qup: Add V2 tags support
  i2c: qup: Transfer each i2c_msg in i2c_msgs without a stop bit
  i2c: qup: Add bam dma capabilities
  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| 931 ++--
 2 files changed, 896 insertions(+), 49 deletions(-)

-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V5 3/6] i2c: qup: Transfer each i2c_msg in i2c_msgs without a stop bit

2015-11-17 Thread Sricharan R
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.

This patch adds the support in non-dma mode.

Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 34 ++
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 715d4d7..f9009d6 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -112,6 +112,7 @@
 #define SET_BIT0x1
 #define RESET_BIT  0x0
 #define ONE_BYTE   0x1
+#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
 
 struct qup_i2c_block {
int count;
@@ -147,6 +148,12 @@ struct qup_i2c_dev {
/* QUP core errors */
u32 qup_err;
 
+   /* To check if this is the last msg */
+   boolis_last;
+
+   /* To configure when bus is in run state */
+   int config_run;
+
struct completion   xfer;
 };
 
@@ -269,7 +276,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
status = readl(qup->base + QUP_I2C_STATUS);
 
if (((opflags & op) >> shift) == val) {
-   if (op == QUP_OUT_NOT_EMPTY) {
+   if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
if (!(status & I2C_STATUS_BUS_ACTIVE))
return 0;
} else {
@@ -290,6 +297,8 @@ static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev 
*qup,
/* Number of entries to shift out, including the tags */
int total = msg->len + qup->blk.tx_tag_len;
 
+   total |= qup->config_run;
+
if (total < qup->out_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
@@ -443,7 +452,7 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev 
*qup,
}
 
/* Send _STOP commands for the last block */
-   if (qup->blk.pos == (qup->blk.count - 1)) {
+   if ((qup->blk.pos == (qup->blk.count - 1)) && qup->is_last) {
if (msg->flags & I2C_M_RD)
tags[len++] = QUP_TAG_V2_DATARD_STOP;
else
@@ -581,7 +590,6 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
 
/* Wait for the outstanding data in the fifo to drain */
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
-
 err:
disable_irq(qup->irq);
qup->msg = NULL;
@@ -608,18 +616,20 @@ static void qup_i2c_set_read_mode_v2(struct qup_i2c_dev 
*qup, int len)
int tx_len = qup->blk.tx_tag_len;
 
len += qup->blk.rx_tag_len;
+   len |= qup->config_run;
+   tx_len |= qup->config_run;
 
if (len < qup->in_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
-   writel(len, qup->base + QUP_MX_READ_CNT);
writel(tx_len, qup->base + QUP_MX_WRITE_CNT);
+   writel(len, qup->base + QUP_MX_READ_CNT);
} else {
/* BLOCK mode (transfer data on chunks) */
writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN,
   qup->base + QUP_IO_MODE);
-   writel(len, qup->base + QUP_MX_INPUT_CNT);
writel(tx_len, qup->base + QUP_MX_OUTPUT_CNT);
+   writel(len, qup->base + QUP_MX_INPUT_CNT);
}
 }
 
@@ -866,6 +876,12 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
goto out;
}
 
+   qup->is_last = (idx == (num - 1));
+   if (idx)
+   qup->config_run = QUP_I2C_MX_CONFIG_DURING_RUN;
+   else
+   qup->config_run = 0;
+
reinit_completion(&qup->xfer);
 
if (msgs[idx].flags & I2C_M_RD)
@@ -873,13 +889,13 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
else
ret = qup

[PATCH V5 5/6] dts: msm8974: Add blsp2_bam dma node

2015-11-17 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 753bdfd..7786408 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include 
+#include 
 #include 
 #include "skeleton.dtsi"
 
@@ -345,6 +345,16 @@
interrupt-controller;
#interrupt-cells = <4>;
};
+
+   blsp2_dma: dma-controller@f9944000 {
+   compatible = "qcom,bam-v1.4.0";
+   reg = <0xf9944000 0x19000>;
+   interrupts = ;
+   clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+   clock-names = "bam_clk";
+   #dma-cells = <1>;
+   qcom,ee = <0>;
+   };
};
 
smd {
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V5 2/6] i2c: qup: Add V2 tags support

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

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

Signed-off-by: Andy Gross 
Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 415 ---
 1 file changed, 386 insertions(+), 29 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 81ed120..715d4d7 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -42,6 +42,7 @@
 #define QUP_IN_FIFO_BASE   0x218
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
+#define QUP_I2C_MASTER_GEN 0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
@@ -69,6 +70,8 @@
 #define QUP_CLOCK_AUTO_GATEBIT(13)
 #define I2C_MINI_CORE  (2 << 8)
 #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
 /* Most significant word offset in FIFO port */
 #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)
 
@@ -79,6 +82,7 @@
 #define QUP_PACK_ENBIT(15)
 
 #define QUP_REPACK_EN  (QUP_UNPACK_EN | QUP_PACK_EN)
+#define QUP_V2_TAGS_EN 1
 
 #define QUP_OUTPUT_BLOCK_SIZE(x)(((x) >> 0) & 0x03)
 #define QUP_OUTPUT_FIFO_SIZE(x)(((x) >> 2) & 0x07)
@@ -91,6 +95,13 @@
 #define QUP_TAG_STOP   (3 << 8)
 #define QUP_TAG_REC(4 << 8)
 
+/* QUP v2 tags */
+#define QUP_TAG_V2_START   0x81
+#define QUP_TAG_V2_DATAWR  0x82
+#define QUP_TAG_V2_DATAWR_STOP 0x83
+#define QUP_TAG_V2_DATARD  0x85
+#define QUP_TAG_V2_DATARD_STOP 0x87
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL  BIT(0)
 #define I2C_STATUS_BUS_ACTIVE  BIT(8)
@@ -102,6 +113,15 @@
 #define RESET_BIT  0x0
 #define ONE_BYTE   0x1
 
+struct qup_i2c_block {
+   int count;
+   int pos;
+   int tx_tag_len;
+   int rx_tag_len;
+   int data_len;
+   u8  tags[6];
+};
+
 struct qup_i2c_dev {
struct device   *dev;
void __iomem*base;
@@ -117,6 +137,7 @@ struct qup_i2c_dev {
int in_blk_sz;
 
unsigned long   one_byte_t;
+   struct qup_i2c_blockblk;
 
struct i2c_msg  *msg;
/* Current posion in user message buffer */
@@ -263,6 +284,24 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
}
 }
 
+static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
+ struct i2c_msg *msg)
+{
+   /* Number of entries to shift out, including the tags */
+   int total = msg->len + qup->blk.tx_tag_len;
+
+   if (total < qup->out_fifo_sz) {
+   /* FIFO mode */
+   writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
+   writel(total, qup->base + QUP_MX_WRITE_CNT);
+   } else {
+   /* BLOCK mode (transfer data on chunks) */
+   writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN,
+  qup->base + QUP_IO_MODE);
+   writel(total, qup->base + QUP_MX_OUTPUT_CNT);
+   }
+}
+
 static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
*msg)
 {
/* Number of entries to shift out, including the start */
@@ -324,9 +363,189 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
return ret;
 }
 
-static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static void qup_i2c_set_blk_data(struct qup_i2c_dev *qup,
+struct i2c_msg *msg)
+{
+   memset(&qup->blk, 0, sizeof(qup->blk));
+
+   qup->blk.data_len = msg->len;
+   qup->blk.count = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT;
+
+   /* 4 bytes for first block and 2 writes for rest */
+   qup->blk.tx_tag_len = 4 + (qup->blk.count - 1) * 2;
+
+   /* There are 2 tag bytes that are read in to fifo for every block */
+   if (msg->flags & I2C_M_RD)
+   qup->blk.rx_tag_len = qup->blk.count * 2;
+}
+
+static int qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
+int dlen, u8 *dbuf)
+{
+   u32 val = 0, idx = 0, pos = 0, i = 0, t;
+   int  len = tlen + dlen;
+   u8 *buf = tbuf;
+   int ret = 0;
+
+   while (len > 0) {
+   ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL,
+RESET

[PATCH V5 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node

2015-11-17 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 7786408..bd1be53 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -328,6 +328,8 @@
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+   dmas = <&blsp2_dma 20>, <&blsp2_dma 21>;
+   dma-names = "tx", "rx";
};
 
spmi_bus: spmi@fc4cf000 {
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V5 4/6] i2c: qup: Add bam dma capabilities

2015-11-17 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 447 ++-
 1 file changed, 439 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index f9009d6..4ca1669 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -14,8 +14,12 @@
  *
  */
 
+#include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -24,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -33,6 +38,7 @@
 #define QUP_OPERATIONAL0x018
 #define QUP_ERROR_FLAGS0x01c
 #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
@@ -52,6 +58,7 @@
 
 #define QUP_STATE_VALIDBIT(2)
 #define QUP_I2C_MAST_GEN   BIT(4)
+#define QUP_I2C_FLUSH  BIT(6)
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfc
@@ -77,7 +84,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_ENBIT(15)
 
@@ -94,6 +104,8 @@
 #define QUP_TAG_DATA   (2 << 8)
 #define QUP_TAG_STOP   (3 << 8)
 #define QUP_TAG_REC(4 << 8)
+#define QUP_BAM_INPUT_EOT  0x93
+#define QUP_BAM_FLUSH_STOP 0x96
 
 /* QUP v2 tags */
 #define QUP_TAG_V2_START   0x81
@@ -114,6 +126,12 @@
 #define ONE_BYTE   0x1
 #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 count;
int pos;
@@ -123,6 +141,17 @@ struct qup_i2c_block {
u8  tags[6];
 };
 
+struct qup_i2c_tag {
+   u8 *start;
+   dma_addr_t addr;
+};
+
+struct qup_i2c_bam {
+   struct  qup_i2c_tag tag;
+   struct  dma_chan *dma;
+   struct  scatterlist *sg;
+};
+
 struct qup_i2c_dev {
struct device   *dev;
void __iomem*base;
@@ -154,6 +183,13 @@ struct qup_i2c_dev {
/* To configure when bus is in run state */
int config_run;
 
+   /* dma parameters */
+   boolis_dma;
+   struct  dma_pool *dpool;
+   struct  qup_i2c_tag start_tag;
+   struct  qup_i2c_bam brx;
+   struct  qup_i2c_bam btx;
+
struct completion   xfer;
 };
 
@@ -230,6 +266,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);
@@ -437,12 +481,14 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
 }
 
 static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
-   struct i2c_msg *msg)
+   struct i2c_msg *msg,  int is_dma)
 {
u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
int len = 0;
int data_len;
 
+   int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
+
if (qup->blk.pos == 0) {
tags[len++] = QUP_TAG_V2_START;
tags[len++] = addr & 0xff;
@@ -452,7 +498,7 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev 
*qup,
}
 
/* Send _STOP commands for the last block */
-   if ((qup->blk.pos == (qup->blk.count - 1)) && qup->is_last) {
+   if (last) {
if (msg->flags & I2C_M_RD)
tags[len++] = QUP_TAG_V2_DATARD_STOP;
else
@@ -472,6 +518,11 @@ static int qup_i2c_s

[PATCH 0/5] iommu/msm: Add DT adaptation and generic bindings support

2015-08-12 Thread Sricharan R
The msm_iommu.c driver currently works based on platform data. A single master
device can be connected to more than one iommu and multiple contexts in each
of the iommu. This association between master and iommus was represented
from platform data using parent/child devices. The master drivers were
responsible for attaching all of the iommus/context to a domain. Now the
platform data support is removed and DT support is added. The master/iommus
are added through generic iommu bindings.

This is essentially rework of the patch posted earlier by
Rob Clark . This series folds the changes
in to the existing driver with the addition of generic bindings.

http://www.spinics.net/lists/linux-arm-msm/msg10077.html

This series is based on the IOMMU probe deferral series from
Laurent Pinchart 

https://lkml.org/lkml/2015/5/14/786

Tested this series on ifc6410 board.

Sricharan R (5):
  iommu/msm: Add DT adaptation
  iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
  iommu/msm: Add support for generic master bindings
  iommu/msm: Set cacheability attributes without tex remap
  iommu/msm: Remove driver BROKEN

 .../devicetree/bindings/iommu/msm,iommu-v0.txt |  59 +++
 drivers/iommu/Kconfig  |   1 -
 drivers/iommu/Makefile |   2 +-
 drivers/iommu/msm_iommu.c  | 508 ++---
 drivers/iommu/msm_iommu.h  |  73 ++-
 drivers/iommu/msm_iommu_dev.c  | 392 
 drivers/iommu/msm_iommu_hw-8xxx.h  |  10 +-
 7 files changed, 432 insertions(+), 613 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] iommu/msm: Add support for generic master bindings

2015-08-12 Thread Sricharan R
This adds the xlate callback which gets invoked during
device registration from DT. The master devices gets added
through this. Also adding the iommu_of_setup callback here.

Signed-off-by: Sricharan R 
---
 drivers/iommu/msm_iommu.c | 51 +--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 1210152..1d95d7c 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -702,6 +703,44 @@ static void print_ctx_regs(void __iomem *base, int ctx)
   GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
+static void insert_iommu_master(struct device *dev,
+   struct msm_iommu_dev *iommu,
+   struct of_phandle_args *spec)
+{
+   struct msm_iommu_ctx_dev *master;
+   int sid;
+
+   master = kzalloc(sizeof(*master), GFP_KERNEL);
+   master->of_node = dev->of_node;
+   list_add(&master->list, &iommu->ctx_list);
+
+   for (sid = 0; sid < spec->args_count; sid++)
+   master->mids[sid] = spec->args[sid];
+
+   master->num_mids = spec->args_count;
+}
+
+static int qcom_iommu_of_xlate(struct device *dev,
+  struct of_phandle_args *spec)
+{
+   struct msm_iommu_dev *iommu;
+   unsigned long flags;
+
+   spin_lock_irqsave(&msm_iommu_lock, flags);
+   list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
+   if (iommu->dev->of_node == spec->np)
+   break;
+   }
+
+   if (!iommu || (iommu->dev->of_node != spec->np))
+   return -ENODEV;
+
+   insert_iommu_master(dev, iommu, spec);
+   spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
+   return 0;
+}
+
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
struct msm_iommu_dev *iommu = dev_id;
@@ -737,7 +776,7 @@ fail:
return 0;
 }
 
-static const struct iommu_ops msm_iommu_ops = {
+static struct iommu_ops msm_iommu_ops = {
.capable = msm_iommu_capable,
.domain_alloc = msm_iommu_domain_alloc,
.domain_free = msm_iommu_domain_free,
@@ -748,6 +787,7 @@ static const struct iommu_ops msm_iommu_ops = {
.map_sg = default_iommu_map_sg,
.iova_to_phys = msm_iommu_iova_to_phys,
.pgsize_bitmap = MSM_IOMMU_PGSIZES,
+   .of_xlate = qcom_iommu_of_xlate,
 };
 
 static int msm_iommu_probe(struct platform_device *pdev)
@@ -832,6 +872,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
}
 
list_add(&iommu->dev_node, &qcom_iommu_devices);
+   of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
 
pr_info("device mapped at %p, irq %d with %d ctx banks\n",
iommu->base, iommu->irq, iommu->ncb);
@@ -916,7 +957,13 @@ static int __init msm_iommu_init(void)
return 0;
 }
 
-subsys_initcall(msm_iommu_init);
+static int __init msm_iommu_of_setup(struct device_node *np)
+{
+   msm_iommu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(msm_iommu_of, "qcom,iommu-v0", msm_iommu_of_setup);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko ");
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c

2015-08-12 Thread Sricharan R
There are only two functions left in msm_iommu_dev.c. Move it to
msm_iommu.c and delete the file.

Signed-off-by: Sricharan R 
---
 drivers/iommu/Makefile|   2 +-
 drivers/iommu/msm_iommu.c | 163 +
 drivers/iommu/msm_iommu_dev.c | 204 --
 3 files changed, 164 insertions(+), 205 deletions(-)
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6dcc51..83ee0bf 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 6024d71..1210152 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -85,6 +86,47 @@ static void __disable_clocks(struct msm_iommu_dev *iommu)
clk_disable_unprepare(iommu->pclk);
 }
 
+static void msm_iommu_reset(void __iomem *base, int ncb)
+{
+   int ctx;
+
+   SET_RPUE(base, 0);
+   SET_RPUEIE(base, 0);
+   SET_ESRRESTORE(base, 0);
+   SET_TBE(base, 0);
+   SET_CR(base, 0);
+   SET_SPDMBE(base, 0);
+   SET_TESTBUSCR(base, 0);
+   SET_TLBRSW(base, 0);
+   SET_GLOBAL_TLBIALL(base, 0);
+   SET_RPU_ACR(base, 0);
+   SET_TLBLKCRWE(base, 1);
+
+   for (ctx = 0; ctx < ncb; ctx++) {
+   SET_BPRCOSH(base, ctx, 0);
+   SET_BPRCISH(base, ctx, 0);
+   SET_BPRCNSH(base, ctx, 0);
+   SET_BPSHCFG(base, ctx, 0);
+   SET_BPMTCFG(base, ctx, 0);
+   SET_ACTLR(base, ctx, 0);
+   SET_SCTLR(base, ctx, 0);
+   SET_FSRRESTORE(base, ctx, 0);
+   SET_TTBR0(base, ctx, 0);
+   SET_TTBR1(base, ctx, 0);
+   SET_TTBCR(base, ctx, 0);
+   SET_BFBCR(base, ctx, 0);
+   SET_PAR(base, ctx, 0);
+   SET_FAR(base, ctx, 0);
+   SET_CTX_TLBIALL(base, ctx, 0);
+   SET_TLBFLPTER(base, ctx, 0);
+   SET_TLBSLPTER(base, ctx, 0);
+   SET_TLBLKCR(base, ctx, 0);
+   SET_PRRR(base, ctx, 0);
+   SET_NMRR(base, ctx, 0);
+   SET_CONTEXTIDR(base, ctx, 0);
+   }
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
struct msm_priv *priv = to_msm_priv(domain);
@@ -708,6 +750,127 @@ static const struct iommu_ops msm_iommu_ops = {
.pgsize_bitmap = MSM_IOMMU_PGSIZES,
 };
 
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+   struct resource *r;
+   struct msm_iommu_dev *iommu;
+   int ret, par, val;
+
+   iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+   if (!iommu) {
+   ret = -ENODEV;
+   goto fail;
+   }
+
+   iommu->dev = &pdev->dev;
+   INIT_LIST_HEAD(&iommu->ctx_list);
+
+   iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+   if (IS_ERR(iommu->pclk)) {
+   dev_err(iommu->dev, "could not get smmu_pclk\n");
+   ret = PTR_ERR(iommu->pclk);
+   goto fail;
+   }
+
+   iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+   if (IS_ERR(iommu->clk)) {
+   dev_err(iommu->dev, "could not get iommu_clk\n");
+   ret = PTR_ERR(iommu->clk);
+   iommu->pclk = NULL;
+   goto fail;
+   }
+
+   r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   iommu->base = devm_ioremap_resource(iommu->dev, r);
+   if (IS_ERR(iommu->base)) {
+   dev_err(iommu->dev, "could not get iommu base\n");
+   ret = PTR_ERR(iommu->base);
+   goto fail;
+   }
+
+   iommu->irq = platform_get_irq(pdev, 0);
+   if (iommu->irq < 0) {
+   dev_err(iommu->dev, "could not get iommu irq\n");
+   ret = -ENODEV;
+   goto fail;
+   }
+
+   ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
+   if (ret) {
+   dev_err(iommu->dev, "could not get ncb\n");
+   goto fail;
+   }
+   iommu->ncb = val;
+
+   __enable_clocks(iommu);
+
+   msm_iommu_reset(iommu->base, iommu->ncb);
+   SET_M(iommu->base, 0, 1);
+   SET_PAR(iommu->base, 0, 0);
+   SET_V2PCFG(iomm

[PATCH 5/5] iommu/msm: Remove driver BROKEN

2015-08-12 Thread Sricharan R
Now that the driver is DT adapted, bus_set_iommu gets called
only when on compatible matching. So the driver should not
break multiplatform  builds now. So remove the BROKEN config.

Signed-off-by: Sricharan R 
---
 drivers/iommu/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f1fb1d3..147de52 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -64,7 +64,6 @@ config MSM_IOMMU
bool "MSM IOMMU Support"
depends on ARM
depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
-   depends on BROKEN
select IOMMU_API
help
  Support for the IOMMUs found on certain Qualcomm SOCs.
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] iommu/msm: Set cacheability attributes without tex remap

2015-08-12 Thread Sricharan R
The cacheablity attributes are set when IOMMU_CACHE property
is true. So cachebility is set as either noncached (normal)
or cached (normal WBWA) directly and avoid setting using
tex remap.

Signed-off-by: Sricharan R 
---
 drivers/iommu/msm_iommu.c | 66 +++
 drivers/iommu/msm_iommu_hw-8xxx.h | 10 ++
 2 files changed, 8 insertions(+), 68 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 1d95d7c..d554ffa 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -41,14 +41,9 @@ __asm__ __volatile__ (   
\
 "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
 : "=r" (reg))
 
-#define RCP15_PRRR(reg)MRC(reg, p15, 0, c10, c2, 0)
-#define RCP15_NMRR(reg)MRC(reg, p15, 0, c10, c2, 1)
-
 /* bitmap of the page sizes currently supported */
 #define MSM_IOMMU_PGSIZES  (SZ_4K | SZ_64K | SZ_1M | SZ_16M)
 
-static int msm_iommu_tex_class[4];
-
 DEFINE_SPINLOCK(msm_iommu_lock);
 static LIST_HEAD(qcom_iommu_devices);
 
@@ -122,8 +117,6 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
SET_TLBFLPTER(base, ctx, 0);
SET_TLBSLPTER(base, ctx, 0);
SET_TLBLKCR(base, ctx, 0);
-   SET_PRRR(base, ctx, 0);
-   SET_NMRR(base, ctx, 0);
SET_CONTEXTIDR(base, ctx, 0);
}
 }
@@ -232,13 +225,10 @@ static void __reset_context(void __iomem *base, int ctx)
SET_TLBFLPTER(base, ctx, 0);
SET_TLBSLPTER(base, ctx, 0);
SET_TLBLKCR(base, ctx, 0);
-   SET_PRRR(base, ctx, 0);
-   SET_NMRR(base, ctx, 0);
 }
 
 static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 {
-   unsigned int prrr, nmrr;
__reset_context(base, ctx);
 
/* Set up HTW mode */
@@ -268,15 +258,6 @@ static void __program_context(void __iomem *base, int ctx, 
phys_addr_t pgtable)
SET_RCOSH(base, ctx, 1);
SET_RCNSH(base, ctx, 1);
 
-   /* Turn on TEX Remap */
-   SET_TRE(base, ctx, 1);
-
-   /* Set TEX remap attributes */
-   RCP15_PRRR(prrr);
-   RCP15_NMRR(nmrr);
-   SET_PRRR(base, ctx, prrr);
-   SET_NMRR(base, ctx, nmrr);
-
/* Turn on BFB prefetch */
SET_BFBDFE(base, ctx, 1);
 
@@ -452,7 +433,11 @@ static int msm_iommu_map(struct iommu_domain *domain, 
unsigned long va,
spin_lock_irqsave(&msm_iommu_lock, flags);
 
sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-   tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
+
+   tex = TEX_0;
+
+   if (prot & IOMMU_CACHE)
+   tex |= BUFFERABLE | CACHEABLE;
 
if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
ret = -EINVAL;
@@ -699,8 +684,6 @@ static void print_ctx_regs(void __iomem *base, int ctx)
   GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
pr_err("SCTLR  = %08xACTLR  = %08x\n",
   GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
-   pr_err("PRRR   = %08xNMRR   = %08x\n",
-  GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
 static void insert_iommu_master(struct device *dev,
@@ -912,47 +895,8 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init get_tex_class(int icp, int ocp, int mt, int nos)
-{
-   int i = 0;
-   unsigned int prrr = 0;
-   unsigned int nmrr = 0;
-   int c_icp, c_ocp, c_mt, c_nos;
-
-   RCP15_PRRR(prrr);
-   RCP15_NMRR(nmrr);
-
-   for (i = 0; i < NUM_TEX_CLASS; i++) {
-   c_nos = PRRR_NOS(prrr, i);
-   c_mt = PRRR_MT(prrr, i);
-   c_icp = NMRR_ICP(nmrr, i);
-   c_ocp = NMRR_OCP(nmrr, i);
-
-   if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
-   return i;
-   }
-
-   return -ENODEV;
-}
-
-static void __init setup_iommu_tex_classes(void)
-{
-   msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
-   get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
-
-   msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
-   get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
-
-   msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
-   get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
-
-   msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
-   get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
-}
-
 static int __init msm_iommu_init(void)
 {
-   setup_iommu_tex_classes();
bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
return 0;
 }
diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h 
b/drivers/iommu/msm_iommu_hw-8xxx.h
ind

[PATCH 1/5] iommu/msm: Add DT adaptation

2015-08-12 Thread Sricharan R
The driver currently works based on platform data. Remove this
and add support for DT. A single master can have multiple ports
connected to more than one iommu.

  master
|
|
|
   
   |  |
IOMMU0  IOMMU1
   |  |
  ctx0   ctx1ctx0   ctx1

This association of master and iommus/contexts were previously
represented by platform data parent/child device details. The client
drivers were responsible for programming all of the iommus/contexts
for the device. Now while adapting to generic DT bindings we maintain the
list of iommus, contexts that each master domain is connected to and
program all of them on attach/detach.

Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/iommu/msm,iommu-v0.txt |  59 
 drivers/iommu/msm_iommu.c  | 252 
 drivers/iommu/msm_iommu.h  |  73 ++---
 drivers/iommu/msm_iommu_dev.c  | 320 +
 4 files changed, 289 insertions(+), 415 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt

diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt 
b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
new file mode 100644
index 000..21bfbfc
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
@@ -0,0 +1,59 @@
+* QCOM IOMMU
+
+The QCOM IOMMU is an implementation compatible with the ARM VMSA short
+descriptor page tables. It provides address translation for bus masters outside
+of the CPU, each connected to the IOMMU through a port called micro-TLB.
+
+Required Properties:
+
+  - compatible: Must contain "qcom,iommu-v0".
+  - reg: Base address and size of the IOMMU registers.
+  - interrupts: Specifiers for the MMU fault interrupts. For instances that
+support secure mode two interrupts must be specified, for non-secure and
+secure mode, in that order. For instances that don't support secure mode a
+single interrupt must be specified.
+  - #iommu-cells: This is the total number of stream ids that a master would
+ use during transactions which will be specified as a list
+ as a part of iommus property below.
+  - ncb: The total number of context banks in the IOMMU.
+  - clocks : List of clocks to be used during SMMU register access. See
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ for information about the format. For each clock specified
+ here, there must be a corresponding entry in clock-names
+ (see below).
+
+  - clock-names: List of clock names corresponding to the clocks 
specified in
+ the "clocks" property (above). See
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ for more info.
+
+Each bus master connected to an IOMMU must reference the IOMMU in its device
+node with the following property:
+
+  - iommus: A reference to the IOMMU in multiple cells. The first cell is a
+   phandle to the IOMMU and the second cell is the list of the
+   stream ids used by the device.
+
+Example: mdp iommu and its bus master
+
+mdp_port0: qcom,iommu@750 {
+   compatible = "qcom,iommu-v0";
+   #iommu-cells = <2>;
+   clock-names =
+   "smmu_pclk",
+   "iommu_clk";
+   clocks =
+   <&mmcc SMMU_AHB_CLK>,
+   <&mmcc MDP_AXI_CLK>;
+   reg = <0x0750 0x10>;
+   interrupts =
+   ,
+   ;
+   ncb = <2>;
+   };
+
+   mdp: qcom,mdp@510 {
+   compatible = "qcom,mdp";
+   ...
+   iommus = <&mdp_port0 0 2>;
+   };
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 15a2063..6024d71 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -48,6 +48,7 @@ __asm__ __volatile__ (
\
 static int msm_iommu_tex_class[4];
 
 DEFINE_SPINLOCK(msm_iommu_lock);
+static LIST_HEAD(qcom_iommu_devices);
 
 struct msm_priv {
unsigned long *pgtable;
@@ -60,35 +61,37 @@ static struct msm_priv *to_msm_priv(struct iommu_domain 
*dom)
return container_of(dom, struct msm_priv, domain);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+static int __enable_clocks(struct msm_iommu_

[RFC PATCH 4/4] iommu/arm-smmu: Add support for specifying regulators

2015-07-17 Thread Sricharan R
From: Mitchel Humpherys 

This adds the support to turn on the regulators required
for SMMUs. It is turned on during the SMMU probe and remains
'on' till the device exists.

Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/iommu/arm,smmu.txt |  3 ++
 drivers/iommu/arm-smmu.c   | 48 +-
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index c2cf4fe..433d778 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -60,6 +60,9 @@ conditions.
  Documentation/devicetree/bindings/clock/clock-bindings.txt
  for more info.
 
+- vdd-supply: Phandle of the regulator that should be powered on during
+  SMMU register access.
+
 Example:
 
 smmu {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 80d56f0a..c92de50 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -326,6 +326,8 @@ struct arm_smmu_device {
 
int num_clocks;
struct clk  **clocks;
+
+   struct regulator*regulator;
 };
 
 struct arm_smmu_cfg {
@@ -559,6 +561,22 @@ static void __arm_smmu_free_bitmap(unsigned long *map, int 
idx)
clear_bit(idx, map);
 }
 
+static int arm_smmu_enable_regulators(struct arm_smmu_device *smmu)
+{
+   if (!smmu->regulator)
+   return 0;
+
+   return regulator_enable(smmu->regulator);
+}
+
+static int arm_smmu_disable_regulators(struct arm_smmu_device *smmu)
+{
+   if (!smmu->regulator)
+   return 0;
+
+   return regulator_disable(smmu->regulator);
+}
+
 /* Wait for any pending TLB invalidations to complete */
 static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
 {
@@ -1583,6 +1601,20 @@ static int arm_smmu_id_size_to_bits(int size)
}
 }
 
+static int arm_smmu_init_regulators(struct arm_smmu_device *smmu)
+{
+   struct device *dev = smmu->dev;
+
+   if (!of_get_property(dev->of_node, "vdd-supply", NULL))
+   return 0;
+
+   smmu->regulator = devm_regulator_get(dev, "vdd");
+   if (IS_ERR(smmu->regulator))
+   return PTR_ERR(smmu->regulator);
+
+   return 0;
+}
+
 static int arm_smmu_init_clocks(struct arm_smmu_device *smmu)
 {
const char *cname;
@@ -1841,11 +1873,21 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
smmu->irqs[i] = irq;
}
 
+   err = arm_smmu_init_regulators(smmu);
+   if (err)
+   goto out_put_masters;
+
err = arm_smmu_init_clocks(smmu);
if (err)
goto out_put_masters;
 
-   arm_smmu_enable_clocks(smmu);
+   err = arm_smmu_enable_regulators(smmu);
+   if (err)
+   goto out_put_masters;
+
+   err = arm_smmu_enable_clocks(smmu);
+   if (err)
+   goto out_disable_regulators;
 
err = arm_smmu_device_cfg_probe(smmu);
if (err)
@@ -1908,6 +1950,9 @@ out_free_irqs:
 out_disable_clocks:
arm_smmu_disable_clocks(smmu);
 
+out_disable_regulators:
+   arm_smmu_disable_regulators(smmu);
+
 out_put_masters:
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
struct arm_smmu_master *master
@@ -1953,6 +1998,7 @@ static int arm_smmu_device_remove(struct platform_device 
*pdev)
/* Turn the thing off */
writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
arm_smmu_disable_clocks(smmu);
+   arm_smmu_disable_regulators(smmu);
 
return 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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 2/4] iommu/arm-smmu: Add xlate callback for initializing master devices from dt

2015-07-17 Thread Sricharan R
This adds of_xlate callback to arm-smmu driver. xlate callback
is called during device registration from DT for those master
devices attached to iommus using generic iommu bindings.

Signed-off-by: Sricharan R 
---
 drivers/iommu/arm-smmu.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8c4eb43..2cf65ab 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -321,6 +321,7 @@ struct arm_smmu_device {
unsigned int*irqs;
 
struct list_headlist;
+   struct device_node  *node;
struct rb_root  masters;
 };
 
@@ -1434,6 +1435,38 @@ out_unlock:
return ret;
 }
 
+static int arm_smmu_of_xlate(struct device *dev,
+struct of_phandle_args *spec)
+{
+   struct arm_smmu_device *smmu;
+   struct arm_smmu_master *master;
+   int streamid;
+
+   spin_lock(&arm_smmu_devices_lock);
+   list_for_each_entry(smmu, &arm_smmu_devices, list) {
+   if (smmu->node == spec->np)
+   break;
+   }
+   spin_unlock(&arm_smmu_devices_lock);
+
+   if (!smmu || (smmu->node != spec->np))
+   return -ENODEV;
+
+   spec->np = dev->of_node;
+
+   master = find_smmu_master(smmu, spec->np);
+   if (!master) {
+   if (register_smmu_master(smmu, smmu->dev, spec))
+   return -ENODEV;
+   } else {
+   streamid = master->cfg.num_streamids;
+   master->cfg.streamids[streamid] = spec->args[0];
+   master->cfg.num_streamids++;
+   }
+
+   return 0;
+}
+
 static struct iommu_ops arm_smmu_ops = {
.capable= arm_smmu_capable,
.domain_init= arm_smmu_domain_init,
@@ -1449,6 +1482,7 @@ static struct iommu_ops arm_smmu_ops = {
.domain_get_attr= arm_smmu_domain_get_attr,
.domain_set_attr= arm_smmu_domain_set_attr,
.pgsize_bitmap  = -1UL, /* Restricted during device attach */
+   .of_xlate   = arm_smmu_of_xlate,
 };
 
 static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
@@ -1782,6 +1816,8 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
}
}
 
+   smmu->node = dev->of_node;
+
INIT_LIST_HEAD(&smmu->list);
spin_lock(&arm_smmu_devices_lock);
list_add(&smmu->list, &arm_smmu_devices);
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 1/4] iommu/arm-smmu: Init driver using IOMMU_OF_DECLARE

2015-07-17 Thread Sricharan R
This patch uses IOMMU_OF_DECLARE to register the driver
and the iommu_ops. So when master devices of the iommu are
registered, of_xlate callback can be used to add the master
configurations to the smmu driver.

Signed-off-by: Sricharan R 
---
 drivers/iommu/arm-smmu.c | 36 +++-
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index fc13dd5..8c4eb43 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -41,6 +41,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -254,6 +256,8 @@
 #define FSYNR0_WNR (1 << 4)
 
 static int force_stage;
+static bool init_done;
+
 module_param_named(force_stage, force_stage, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(force_stage,
"Force SMMU mappings to be installed at a particular stage of 
translation. A value of '1' or '2' forces the corresponding stage. All other 
values are ignored (i.e. no stage is forced). Note that selecting a specific 
stage will disable support for nested translation.");
@@ -1848,20 +1852,8 @@ static struct platform_driver arm_smmu_driver = {
 
 static int __init arm_smmu_init(void)
 {
-   struct device_node *np;
int ret;
 
-   /*
-* Play nice with systems that don't have an ARM SMMU by checking that
-* an ARM SMMU exists in the system before proceeding with the driver
-* and IOMMU bus operation registration.
-*/
-   np = of_find_matching_node(NULL, arm_smmu_of_match);
-   if (!np)
-   return 0;
-
-   of_node_put(np);
-
ret = platform_driver_register(&arm_smmu_driver);
if (ret)
return ret;
@@ -1880,15 +1872,33 @@ static int __init arm_smmu_init(void)
bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
 #endif
 
+   init_done = true;
+
return 0;
 }
 
+static int __init arm_smmu_of_setup(struct device_node *np)
+{
+
+   if (!init_done)
+   arm_smmu_init();
+
+   of_iommu_set_ops(np, &arm_smmu_ops);
+
+   return 0;
+}
+
+IOMMU_OF_DECLARE(arm_smmu_v1, "arm,smmu-v1", arm_smmu_of_setup);
+IOMMU_OF_DECLARE(arm_smmu_v2, "arm,smmu-v2", arm_smmu_of_setup);
+IOMMU_OF_DECLARE(arm_smmu_400, "arm,mmu-400", arm_smmu_of_setup);
+IOMMU_OF_DECLARE(arm_smmu_401, "arm,mmu-401", arm_smmu_of_setup);
+IOMMU_OF_DECLARE(arm_smmu_500, "arm,mmu-500", arm_smmu_of_setup);
+
 static void __exit arm_smmu_exit(void)
 {
return platform_driver_unregister(&arm_smmu_driver);
 }
 
-subsys_initcall(arm_smmu_init);
 module_exit(arm_smmu_exit);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 3/4] iommu/arm-smmu: Add support for specifying clocks

2015-07-17 Thread Sricharan R
From: Mitchel Humpherys 

On some platforms with tight power constraints it is polite to only
leave your clocks on for as long as you absolutely need them. Currently
we assume that all clocks necessary for SMMU register access are always
on.

Add some optional device tree properties to specify any clocks that are
necessary for SMMU register access and turn them on and off as needed.

If no clocks are specified in the device tree things continue to work
the way they always have: we assume all necessary clocks are always
turned on. The clocks are turned 'on' during the SMMU device probe
and remains 'on' till the device exists.

Signed-off-by: Mitchel Humpherys 
Signed-off-by: Sricharan R 
---
 .../devicetree/bindings/iommu/arm,smmu.txt | 11 +++
 drivers/iommu/arm-smmu.c   | 86 +-
 2 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 0676050..c2cf4fe 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -49,6 +49,17 @@ conditions.
   aliases of secure registers have to be used during
   SMMU configuration.
 
+- clocks   : List of clocks to be used during SMMU register access. See
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ for information about the format. For each clock specified
+ here, there must be a corresponding entery in clock-names
+ (see below).
+
+- clock-names  : List of clock names corresponding to the clocks specified in
+ the "clocks" property (above). See
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ for more info.
+
 Example:
 
 smmu {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2cf65ab..80d56f0a 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -323,6 +323,9 @@ struct arm_smmu_device {
struct list_headlist;
struct device_node  *node;
struct rb_root  masters;
+
+   int num_clocks;
+   struct clk  **clocks;
 };
 
 struct arm_smmu_cfg {
@@ -365,6 +368,31 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
{ 0, NULL},
 };
 
+static int arm_smmu_enable_clocks(struct arm_smmu_device *smmu)
+{
+   int i, ret = 0;
+
+   for (i = 0; i < smmu->num_clocks; ++i) {
+   ret = clk_prepare_enable(smmu->clocks[i]);
+   if (ret) {
+   dev_err(smmu->dev, "Couldn't enable clock #%d\n", i);
+   while (i--)
+   clk_disable_unprepare(smmu->clocks[i]);
+   break;
+   }
+   }
+
+   return ret;
+}
+
+static void arm_smmu_disable_clocks(struct arm_smmu_device *smmu)
+{
+   int i;
+
+   for (i = 0; i < smmu->num_clocks; ++i)
+   clk_disable_unprepare(smmu->clocks[i]);
+}
+
 static void parse_driver_options(struct arm_smmu_device *smmu)
 {
int i = 0;
@@ -1555,6 +1583,47 @@ static int arm_smmu_id_size_to_bits(int size)
}
 }
 
+static int arm_smmu_init_clocks(struct arm_smmu_device *smmu)
+{
+   const char *cname;
+   struct property *prop;
+   int i;
+   struct device *dev = smmu->dev;
+
+   smmu->num_clocks =
+   of_property_count_strings(dev->of_node, "clock-names");
+
+   if (smmu->num_clocks < 1)
+   return 0;
+
+   smmu->clocks = devm_kzalloc(
+   dev, sizeof(*smmu->clocks) * smmu->num_clocks,
+   GFP_KERNEL);
+
+   if (!smmu->clocks) {
+   dev_err(dev,
+   "Failed to allocate memory for clocks\n");
+   return -ENODEV;
+   }
+
+   i = 0;
+   of_property_for_each_string(dev->of_node, "clock-names",
+   prop, cname) {
+   struct clk *c = devm_clk_get(dev, cname);
+
+   if (IS_ERR(c)) {
+   dev_err(dev, "Couldn't get clock: %s",
+   cname);
+   return -ENODEV;
+   }
+
+   smmu->clocks[i] = c;
+
+   ++i;
+   }
+   return 0;
+}
+
 static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 {
unsigned long size;
@@ -1772,9 +1841,15 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
smmu->irqs[i] = irq;
}
 
+   err = arm_smmu_init_clocks(smmu);
+   if (err)
+   goto out_put_masters;
+
+   arm_smmu_enab

[RFC PATCH 0/4] iommu/arm-smmu: Add support for adding masters/clocks using generic bindings

2015-07-17 Thread Sricharan R
This series adds support for xlate callback to add master
devices configs using generic bindings and clocks/regulators
required to access smmu.

OF_IOMMU_DECLARE is used to register and probe the smmu controller
devices before the masters are added in of_platform_populate.
Here, we are registering only the smmu driver and iommu_ops. The
smmu device registration is not done in OF_IOMMU_DECLARE to avoid
early smmu probe, because the clocks if any required for the controller
are not yet ready.

So the idea here is to get the right direction in adding this support.

Mitchel Humpherys (2):
  iommu/arm-smmu: add support for specifying clocks
  iommu/arm-smmu: Add support for specifying regulators

Sricharan R (2):
  iommu/arm-smmu: Init driver using IOMMU_OF_DECLARE
  iommu/arm-smmu: Add xlate callback for initializing master devices
from dt

 .../devicetree/bindings/iommu/arm,smmu.txt |  14 ++
 drivers/iommu/arm-smmu.c   | 210 +++--
 2 files changed, 208 insertions(+), 16 deletions(-)

-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC] drivers: dma-coherent: Change order of allocation to PAGE_SIZE

2015-07-08 Thread Sricharan R
dma_alloc_from_coherent uses get_order(size) which makes carve-out
allocations not aligned on order boundaries to fail even though
they are page aligned. So wanted to know why is it required to have
the size aligned on order boundary. Changing it to get_order(PAGE_SIZE)
makes the non aligned carve-out allocations to go through.

Signed-off-by: Sricharan R 
---
 drivers/base/dma-coherent.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index 55b8398..72bdc6f 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -156,7 +156,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t 
size,
   dma_addr_t *dma_handle, void **ret)
 {
struct dma_coherent_mem *mem;
-   int order = get_order(size);
+   int order = get_order(PAGE_SIZE);
unsigned long flags;
int pageno;
 
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 6/7] dts: msm8974: Add blsp2_bam dma node

2015-07-08 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 37b47b5..f138202 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include 
+#include 
 #include 
 #include "skeleton.dtsi"
 
@@ -301,5 +301,15 @@
interrupt-controller;
#interrupt-cells = <4>;
};
+
+   blsp2_dma: dma-controller@f9944000 {
+   compatible = "qcom,bam-v1.4.0";
+   reg = <0xf9944000 0x19000>;
+   interrupts = ;
+   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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 2/7] qup: i2c: factor out common code for reuse

2015-07-08 Thread Sricharan R
The qup_i2c_write/read_one functions can be split to have
the common initialization code and function to loop around
the data bytes separately. This way the initialization code
can be reused while adding v2 tags functionality.

Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 147 +--
 1 file changed, 87 insertions(+), 60 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 81ed120..131dc28 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -324,53 +324,72 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
return ret;
 }
 
-static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
+struct i2c_msg *msg)
 {
unsigned long left;
-   int ret;
-
-   qup->msg = msg;
-   qup->pos = 0;
+   int ret = 0;
 
-   enable_irq(qup->irq);
+   left = wait_for_completion_timeout(&qup->xfer, HZ);
+   if (!left) {
+   writel(1, qup->base + QUP_SW_RESET);
+   ret = -ETIMEDOUT;
+   }
 
-   qup_i2c_set_write_mode(qup, msg);
+   if (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;
+   }
+   }
 
-   ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
-   if (ret)
-   goto err;
+   return ret;
+}
 
-   writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+   int ret = 0;
 
do {
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret)
-   goto err;
+   return ret;
 
ret = qup_i2c_issue_write(qup, msg);
if (ret)
-   goto err;
+   return ret;
 
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
-   goto err;
-
-   left = wait_for_completion_timeout(&qup->xfer, HZ);
-   if (!left) {
-   writel(1, qup->base + QUP_SW_RESET);
-   ret = -ETIMEDOUT;
-   goto err;
-   }
+   return ret;
 
-   if (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;
-   goto err;
-   }
+   ret = qup_i2c_wait_for_complete(qup, msg);
+   if (ret)
+   return ret;
} while (qup->pos < msg->len);
 
-   /* Wait for the outstanding data in the fifo to drain */
+   return ret;
+}
+
+static int qup_i2c_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+{
+   int ret;
+
+   qup->msg = msg;
+   qup->pos = 0;
+   enable_irq(qup->irq);
+   qup_i2c_set_write_mode(qup, msg);
+
+   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_write_one(qup, msg);
+   if (ret)
+   goto err;
+
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
 
 err:
@@ -436,51 +455,59 @@ static int 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)
 {
-   unsigned long left;
-   int ret;
+   int ret = 0;
 
-   qup->msg = msg;
-   qup->pos  = 0;
+   /*
+* 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
+* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
+*/
+   if (msg->len > QUP_READ_LIMIT) {
+   dev_err(qup->dev, "HW not capable of reads over %d bytes\n",
+   QUP_READ_LIMIT);
+   return -EINVAL;
+   }
 
-   enable_irq(qup->irq);
+   ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+   if (ret)
+   return ret;
 
-   qup_i2c_set_read_mode(qup, msg->len);
+   qup_i2c_issue_read(qup, msg);
 
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
-   goto err;
+   return ret;
 
-   writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+   do {
+   ret = qup_i2c_wait_for_c

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

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

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

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

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

[PATCH V4 5/7] i2c: qup: Add bam dma capabilities

2015-07-08 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 431 +--
 1 file changed, 415 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c0757d9..810b021 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -24,6 +24,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -33,6 +38,7 @@
 #define QUP_OPERATIONAL0x018
 #define QUP_ERROR_FLAGS0x01c
 #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_VALIDBIT(2)
 #define QUP_I2C_MAST_GEN   BIT(4)
+#define QUP_I2C_FLUSH  BIT(6)
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfc
@@ -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_ENBIT(15)
 
@@ -95,6 +105,8 @@
 #define QUP_TAG_DATA   (2 << 8)
 #define QUP_TAG_STOP   (3 << 8)
 #define QUP_TAG_REC(4 << 8)
+#define QUP_BAM_INPUT_EOT  0x93
+#define QUP_BAM_FLUSH_STOP 0x96
 
 /* QUP v2 tags */
 #define QUP_TAG_V2_START   0x81
@@ -115,6 +127,12 @@
 #define ONE_BYTE   0x1
 #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 count;
int pos;
@@ -125,6 +143,23 @@ struct qup_i2c_block {
int config_run;
 };
 
+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;
@@ -154,14 +189,20 @@ struct qup_i2c_dev {
 
int (*qup_i2c_write_one)(struct qup_i2c_dev *qup,
 struct i2c_msg *msg);
+   int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
+   struct i2c_msg *msg);
+
/* Current i2c_msg in i2c_msgs */
int cmsg;
/* total num of i2c_msgs */
int num;
 
-   int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
-   struct i2c_msg *msg);
-
+   /* dma parameters */
+   boolis_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;
 };
 
@@ -238,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);
@@ -437,12 +486,15 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
 }
 
 static int qup_i2c_get_tags(u8 *tags, struct qup_i2c_dev *qup,
-   struct i2c_msg *msg)
+   struct i2c_msg *msg, int is_dma)
 {
u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
int len = 0;
int data_len;
 
+   int last = (qup->blk.pos == (qup->blk.count - 1)) &&
+   (qup->cmsg == (qup->num - 1));
+
if (qup->blk.pos == 0) {
  

[PATCH V4 0/7] i2c: qup: Add support for v2 tags and bam dma

2015-07-08 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of i2c command tags.
Tag codes instructs the controller to perform a operation like read/write.
This new tagging version supports 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.

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

[V4] Added a patch to factor out some common code.
 Removed support for freq > 400KHZ as per comments.
 Addressed comments from Ivan T. Ivanov to keep the code for
 V2 support in a separate path. 
 Changed the authorship of V2 tags support patch.

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

 http://comments.gmane.org/gmane.linux.drivers.i2c/22497

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

Sricharan R (7):
  i2c: qup: Change qup_wait_writeready function to use for all timeouts
  qup: i2c: factor out common code for reuse
  i2c: qup: Add V2 tags support
  i2c: qup: Transfer each i2c_msg in i2c_msgs without a stop bit
  i2c: qup: Add bam dma capabilities
  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| 943 +---
 2 files changed, 880 insertions(+), 77 deletions(-)

-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 7/7] dts: msm8974: Add dma channels for blsp2_i2c1 node

2015-07-08 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 f138202..17dcda3 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -284,6 +284,8 @@
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+   dmas = <&blsp2_dma 20>, <&blsp2_dma 21>;
+   dma-names = "tx", "rx";
};
 
spmi_bus: spmi@fc4cf000 {
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V4 4/7] i2c: qup: Transfer each i2c_msg in i2c_msgs without a stop bit

2015-07-08 Thread Sricharan R
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.

This patch adds the support in non-dma mode.

Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 40 ++--
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a4e20d9..c0757d9 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -113,6 +113,7 @@
 #define SET_BIT0x1
 #define RESET_BIT  0x0
 #define ONE_BYTE   0x1
+#define QUP_I2C_MX_CONFIG_DURING_RUN   BIT(31)
 
 struct qup_i2c_block {
int count;
@@ -121,6 +122,7 @@ struct qup_i2c_block {
int rx_tag_len;
int data_len;
u8  tags[6];
+   int config_run;
 };
 
 struct qup_i2c_dev {
@@ -152,6 +154,10 @@ struct qup_i2c_dev {
 
int (*qup_i2c_write_one)(struct qup_i2c_dev *qup,
 struct i2c_msg *msg);
+   /* Current i2c_msg in i2c_msgs */
+   int cmsg;
+   /* total num of i2c_msgs */
+   int num;
 
int (*qup_i2c_read_one)(struct qup_i2c_dev *qup,
struct i2c_msg *msg);
@@ -278,7 +284,8 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
status = readl(qup->base + QUP_I2C_STATUS);
 
if (((opflags & op) >> shift) == val) {
-   if (op == QUP_OUT_NOT_EMPTY) {
+   if ((op == QUP_OUT_NOT_EMPTY) &&
+   (qup->cmsg == (qup->num - 1))) {
if (!(status & I2C_STATUS_BUS_ACTIVE))
return 0;
} else {
@@ -301,12 +308,14 @@ static void qup_i2c_set_write_mode(struct qup_i2c_dev 
*qup, struct i2c_msg *msg)
if (total < qup->out_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
-   writel(total, qup->base + QUP_MX_WRITE_CNT);
+   writel(total | qup->blk.config_run,
+  qup->base + QUP_MX_WRITE_CNT);
} else {
/* BLOCK mode (transfer data on chunks) */
writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN,
   qup->base + QUP_IO_MODE);
-   writel(total, qup->base + QUP_MX_OUTPUT_CNT);
+   writel(total | qup->blk.config_run,
+  qup->base + QUP_MX_OUTPUT_CNT);
}
 }
 
@@ -374,6 +383,9 @@ static void qup_i2c_get_blk_data(struct qup_i2c_dev *qup,
/* There are 2 tag bytes that are read in to fifo for every block */
if (msg->flags & I2C_M_RD)
qup->blk.rx_tag_len = qup->blk.count * 2;
+
+   if (qup->cmsg)
+   qup->blk.config_run = QUP_I2C_MX_CONFIG_DURING_RUN;
 }
 
 static int qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
@@ -440,7 +452,8 @@ static int qup_i2c_get_tags(u8 *tags, struct qup_i2c_dev 
*qup,
}
 
/* Send _STOP commands for the last block */
-   if (qup->blk.pos == (qup->blk.count - 1)) {
+   if (qup->blk.pos == (qup->blk.count - 1)
+   && (qup->cmsg == (qup->num - 1))) {
if (msg->flags & I2C_M_RD)
tags[len++] = QUP_TAG_V2_DATARD_STOP;
else
@@ -571,7 +584,6 @@ static int qup_i2c_write(struct qup_i2c_dev *qup, struct 
i2c_msg *msg)
goto err;
 
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
-
 err:
disable_irq(qup->irq);
qup->msg = NULL;
@@ -584,18 +596,19 @@ static void qup_i2c_set_read_mode(struct qup_i2c_dev 
*qup, int len)
int tx_len = qup->blk.tx_tag_len;
 
len += qup->blk.rx_tag_len;
+   tx_len |= qup->blk.config_run;
 
if (len < qup->in_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
-   writel(len, qup->base + QUP_MX_READ

[PATCH V4 1/7] i2c: qup: Change qup_wait_writeready function to use for all timeouts

2015-07-08 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 67 +++-
 1 file changed, 48 insertions(+), 19 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index fdcbdab..81ed120 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_BIT0x1
+#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);
}
 }
 
@@ -261,13 +280,13 @@ 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 int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 {
u32 addr = msg->addr << 1;
u32 qup_tag;
-   u32 opflags;
int idx;
u32 val;
+   int ret = 0;
 
if (qup->pos == 0) {
val = QUP_TAG_START | addr;
@@ -279,9 +298,10 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
 
while (qup->pos < msg->len) {
/* Check that there's space in the FIFO for our pair */
-   opflags = readl(qup->base + QUP_OPERATIONAL);
-   if (opflags & QUP_OUT_FULL)
-   break;
+   ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL, RESET_BIT,
+4 * ONE_BYTE);
+   if (ret)
+   return ret;
 
if (qup->pos == msg->len - 1)
qup_tag = QUP_TAG_STOP;
@@ -300,6 +320,8 @@ static void qup_i2c_issue_write(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
qup->pos++;
idx++;
}
+
+   return ret;
 }
 
 static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
@@ -325,7 +347,9 @@ static int qup_i2c_write_one(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
if (ret)
goto err;
 
-   qup_i2c_issue_write(qup, msg);
+   ret = qup_i2c_issue_write(qup, msg);
+   if (ret)
+   goto err;
 
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
@@ -347,7 +371,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);
@@ -384,18 +408,19 @@ static void qup_i2c_issue_read(struct qup_i2c_dev *qup, 
struct i2c_msg *msg)
 }
 
 
-static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg)
+static int qup_i2c_

[PATCH] iommu/arm-smmu: Fix bug in ARM_SMMU_FEAT_TRANS_OPS condition check

2015-06-23 Thread Sricharan R
Patch 'fix ARM_SMMU_FEAT_TRANS_OPS condition' changed the check
for ARM_SMMU_FEAT_TRANS_OPS to be based on presence of stage1 check,
but used (id & ID0_ATOSNS) instead of !(id & ID0_ATOSNS).
Fix it here.

Signed-off-by: Sricharan R 
---
 drivers/iommu/arm-smmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 09091e9..fbf4af6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1866,7 +1866,7 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
return -ENODEV;
}
 
-   if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
+   if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) {
smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
dev_notice(smmu->dev, "\taddress translation ops\n");
}
-- 
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support

2015-04-16 Thread Sricharan R

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.


+stati

Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support

2015-04-15 Thread Sricharan R

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  100


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;
+   booluse_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

Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support

2015-04-15 Thread Sricharan R

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  100


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;
+   booluse_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 c

Re: [PATCH V3 2/6] i2c: qup: Add V2 tags support

2015-04-14 Thread Sricharan R

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 

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 
Signed-off-by: Sricharan R 
---
[V3] Addressed comments from Andy Gross 
  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 
  #include 
  #include 
+#include 

  /* QUP Registers */
  #define QUP_CONFIG 0x000
@@ -42,6 +43,7 @@
  #define QUP_IN_FIFO_BASE   0x218
  #define QUP_I2C_CLK_CTL0x400
  #define QUP_I2C_STATUS 0x404
+#define QUP_I2C_MASTER_GEN 0x408

  /* QUP States and reset values */
  #define QUP_RESET_STATE0
@@ -69,6 +71,8 @@
  #define QUP_CLOCK_AUTO_GATEBIT(13)
  #define I2C_MINI_CORE  (2 << 8)
  #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
  /* Most significant word offset in FIFO port */
  #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)

@@ -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  100


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;
+   booluse_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?




st

Re: [PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node

2015-04-12 Thread Sricharan R

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 
---
  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
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop

2015-04-11 Thread Sricharan R
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 
---
 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;
+
+   

[PATCH V3 3/6] i2c: qup: Add bam dma capabilities

2015-04-11 Thread Sricharan R
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 
---
[V3] Addressed comments from Andy Gross 
 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 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL0x018
 #define QUP_ERROR_FLAGS0x01c
 #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_VALIDBIT(2)
 #define QUP_I2C_MAST_GEN   BIT(4)
+#define QUP_I2C_FLUSH  BIT(6)
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfc
@@ -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_ENBIT(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  100
 
@@ -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 */
+   boolis_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,
+

[PATCH V3 2/6] i2c: qup: Add V2 tags support

2015-04-11 Thread Sricharan R
From: Andy Gross 

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 
Signed-off-by: Sricharan R 
---
[V3] Addressed comments from Andy Gross 
 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 
 #include 
 #include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -42,6 +43,7 @@
 #define QUP_IN_FIFO_BASE   0x218
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
+#define QUP_I2C_MASTER_GEN 0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATEBIT(13)
 #define I2C_MINI_CORE  (2 << 8)
 #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
 /* Most significant word offset in FIFO port */
 #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)
 
@@ -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  100
+
 /* 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;
+   booluse_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->

[PATCH V3 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts

2015-04-11 Thread Sricharan R
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 
---
[v3] Addressed comments from Andy Gross 

 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_BIT0x1
+#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

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


[PATCH V3 0/6] i2c: qup: Add support for v2 tags and bam dma

2015-04-11 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of i2c command tags.
Tag codes instructs the controller to perform a operation like read/write.
This new tagging version supports 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

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


[PATCH V3 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node

2015-04-11 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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

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


[PATCH V3 5/6] dts: msm8974: Add blsp2_bam dma node

2015-04-11 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 
+#include 
 #include 
 #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 = ;
+   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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V2 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node

2015-04-06 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 [v2] Changed dma channel names as per comments.

 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 c2e8711..5cb0772 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";
};
 
spmi_bus: spmi@fc4cf000 {
-- 
1.8.2.1

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


[PATCH V2 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop

2015-04-06 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 199 ++-
 1 file changed, 121 insertions(+), 78 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 2fd141d..85c326f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -830,76 +830,94 @@ void qup_sg_set_buf(struct scatterlist *sg, void *buf, 
struct qup_i2c_tag *tg,
sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
 }
 
-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_LI

[PATCH V2 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts

2015-04-06 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 30 +++---
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4dad23b..49c6cba 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -221,26 +221,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 +363,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, 0, 1);
 
 err:
disable_irq(qup->irq);
-- 
1.8.2.1

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


[PATCH V2 2/6] i2c: qup: Add V2 tags support

2015-04-06 Thread Sricharan R
From: Andy Gross 

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 
Signed-off-by: Sricharan R 
---
 [v2] Addressed comments from Ivan T. Ivanov 

 drivers/i2c/busses/i2c-qup.c | 336 ++-
 1 file changed, 299 insertions(+), 37 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 49c6cba..8605557 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -42,6 +43,7 @@
 #define QUP_IN_FIFO_BASE   0x218
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
+#define QUP_I2C_MASTER_GEN 0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATEBIT(13)
 #define I2C_MINI_CORE  (2 << 8)
 #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
 /* Most significant word offset in FIFO port */
 #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)
 
@@ -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  100
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL  BIT(0)
 #define I2C_STATUS_BUS_ACTIVE  BIT(8)
@@ -99,6 +116,13 @@
 
 #define QUP_READ_LIMIT 256
 
+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;
@@ -112,9 +136,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;
+   booluse_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;
@@ -262,8 +294,13 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
 
 static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
*msg)
 {
-   /* Number of entries to shift out, including the start */
-   int total = msg->len + 1;
+   /* Total Number of entries to shift out, including the tags */
+   int total;
+
+   if (qup->use_v2_tags)
+   total = msg->len + qup->tx_tag_len;
+   else
+   total = msg->len + 1; /* plus start tag */
 
if (total < qup->out_fifo_sz) {
/* FIFO mode */
@@ -277,7 +314,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;
@@ -318,6 +355,134 @@ static void qup_i2c_issue_write(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)
+{
+   u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+   int len = 0, prev_len = 0;
+   int blocks = 0;
+   int rem;
+ 

[PATCH V2 5/6] dts: msm8974: Add blsp2_bam dma node

2015-04-06 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 [v2] Used macros for interrupts property.

 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 2d11641..c2e8711 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-#include 
+#include 
 #include 
 #include "skeleton.dtsi"
 
@@ -263,5 +263,15 @@
interrupt-controller;
#interrupt-cells = <4>;
};
+
+   blsp2_dma: dma@f9944000 {
+   compatible = "qcom,bam-v1.4.0";
+   reg = <0xf9944000 0x19000>;
+   interrupts = ;
+   clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+   clock-names = "bam_clk";
+   #dma-cells = <1>;
+   qcom,ee = <0>;
+   };
};
 };
-- 
1.8.2.1

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


[PATCH V2 3/6] i2c: qup: Add bam dma capabilities

2015-04-06 Thread Sricharan R
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 
---
 [v2] Addressed comments from Ivan T. Ivanov 

 drivers/i2c/busses/i2c-qup.c | 371 ++-
 1 file changed, 366 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 8605557..2fd141d 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -25,6 +25,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL0x018
 #define QUP_ERROR_FLAGS0x01c
 #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_VALIDBIT(2)
 #define QUP_I2C_MAST_GEN   BIT(4)
+#define QUP_I2C_FLUSH  BIT(6)
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfc
@@ -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_ENBIT(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  100
 
@@ -115,6 +129,11 @@
 #define QUP_STATUS_ERROR_FLAGS 0x7c
 
 #define QUP_READ_LIMIT 256
+#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;
@@ -123,6 +142,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;
@@ -155,6 +191,12 @@ struct qup_i2c_dev {
/* QUP core errors */
u32 qup_err;
 
+   /* dma parameters */
+   boolis_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;
 };
 
@@ -231,6 +273,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);
@@ -715,12 +765,242 @@ 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;
+  

[PATCH V2 0/6] i2c: qup: Add support for v2 tags and bam dma

2015-04-06 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of i2c command tags. Tag 
codes instructs the controller to perform a operation like read/write. This new 
tagging version supports 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

[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| 788 +---
 2 files changed, 748 insertions(+), 54 deletions(-)

-- 
1.8.2.1

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


Re: [PATCH 2/6] i2c: qup: Add V2 tags support

2015-03-26 Thread Sricharan R


Hi Ivan,

On 03/26/2015 01:01 PM, Ivan T. Ivanov wrote:

Hi Sricharan,

On Thu, 2015-03-26 at 11:14 +0530, Sricharan R wrote:



+   if (msg->flags & I2C_M_RD)
+   qup->rx_tag_len = (qup->blocks << 1);


here again.


hmm, why not shift ?


Because it makes reading code harder and because compiler
  is smart enough to choose appropriate instruction for
underling CPU architecture.


ok.

+   else
+   qup->rx_tag_len = 0;
+}
+
+static u32 qup_i2c_xfer_data(struct qup_i2c_dev *qup, int len,
+   u8 *buf, int 
last)
+{


I think that xfer is too vague in this case, prefer write or send.


ok. Will change it to send.

+   static u32 val, idx;


static? please fix.

   That was intentional. Using to pack tag and data in to one word across
   two calls. So preserving val, idx across calls.


Sorry this is no go! Reorganize the code, please.


Ok, will change this function.

Regards,
 Sricharan
--
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 linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/6] i2c: qup: Add bam dma capabilities

2015-03-25 Thread Sricharan R

Hi Ivan,

On 03/25/2015 06:40 PM, Ivan T. Ivanov wrote:


Hi Sricharan,

On Fri, 2015-03-13 at 23:19 +0530, Sricharan R wrote:



  #define QUP_I2C_MASTER_GEN 0x408
+#define QUP_I2C_MASTER_CONFIG  0x408



Unused.


Ok, will remove it

  #define QUP_READ_LIMIT 256
+#define MX_TX_RX_LEN   SZ_64K
+#define MX_BLOCKS  (MX_TX_RX_LEN / QUP_READ_LIMIT)
+
+#define TOUT_MAX   300 /* Max timeout for 32k tx/tx */



seconds, muliseconds?


 Ok. Will add milliseconds.

  struct qup_i2c_config {
 int tag_ver;
 int max_freq;
  };

+struct tag {


Please use consistent naming convention.


ok.

+   u8 *start;
+   dma_addr_t addr;
+};
+
  struct qup_i2c_dev {
 struct device*dev;
 void __iomem*base;
@@ -157,9 +181,35 @@ struct qup_i2c_dev {
 /* QUP core errors */
 u32 qup_err;

+   /* dma parameters */
+   boolis_dma;
+   struct  dma_pool *dpool;
+   struct  tag start_tag;
+   struct  tag scratch_tag;
+   struct  tag footer_tag;
+   struct  dma_chan *dma_tx;
+   struct  dma_chan *dma_rx;
+   struct  scatterlist *sg_tx;
+   struct  scatterlist *sg_rx;
+   dma_addr_tsg_tx_phys;
+   dma_addr_tsg_rx_phys;


Maybe these could be organized in structure per direction.


ok, will group it.

+
 struct completionxfer;
  };

+struct i2c_bam_xfer {


Unused.


 Right. Will remove the whole thing. Thanks.

+   struct qup_i2c_dev *qup;
+   u32 start_len;
+
+   u32 rx_nents;
+   u32 tx_nents;
+
+   struct dma_async_tx_descriptor *tx_desc;
+   dma_cookie_t tx_cookie;
+   struct dma_async_tx_descriptor *rx_desc;
+   dma_cookie_t rx_cookie;


structure per direction.


+};
+


 Infact should be removed.



+static void bam_i2c_callback(void *data)
+{


Please use consistent naming, here and bellow.


ok, will change.

+   struct qup_i2c_dev *qup = data;
+
+   complete(&qup->xfer);
+}
+
+static int get_start_tag(u8 *tag, struct i2c_msg *msg, int first, int last,
+   int blen)
+{
+   u8 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+   u8 op;
+   int len = 0;
+
+   /* 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;
+   }
+
+   if (msg->flags & I2C_M_TEN) {
+   len += 5;
+   tag[0] = QUP_TAG_V2_START;
+   tag[1] = addr;
+   tag[2] = op;
+   tag[3] = blen;
+
+   if (msg->flags & I2C_M_RD && last) {
+   len += 2;
+   tag[4] = QUP_BAM_INPUT_EOT;
+   tag[5] = QUP_BAM_FLUSH_STOP;
+   }
+   } else {
+   if (first) {
+   tag[len++] = QUP_TAG_V2_START;
+   tag[len++] = addr;
+   }
+
+   tag[len++] = op;
+   tag[len++] = blen;
+
+   if (msg->flags & I2C_M_RD & last) {
+   tag[len++] = QUP_BAM_INPUT_EOT;
+   tag[len++] = QUP_BAM_FLUSH_STOP;
+   }
+   }
+
+   return len;
+}


Maybe could be split to 2 functions?


hmm, ok will split couple of small ones.

-static const struct i2c_algorithm qup_i2c_algo = {
+static struct i2c_algorithm qup_i2c_algo = {


Why?


 oops. Should not have been changed. Will fix.

 .master_xfer= qup_i2c_xfer,
 .functionality= qup_i2c_func,
  };
@@ -839,6 +1136,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 u32 clk_freq = 10;
 const struct qup_i2c_config *config;
 const struct of_device_id *of_id;
+   int blocks;

 qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
 if (!qup)
@@ -875,6 +1173,53 @@ static int qup_i2c_probe(struct platform_device *pdev)
 return qup->irq;
 }

+   if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v2.1.1") ||
+   of_device_is_compatible(pdev->dev.of_node,
+   "qcom,i2c-qup-v2.2.1")) {


Logic will be simpler if you check just for version 1 of the controller.

 yes. Will fix it.



+   qup->dma_rx = dma_request_slave_channel(&pdev->dev, "bam-rx");
+


Please use dma_request_slave_channel_reason.

As Andy noted, please use just "rx", "tx"


ok. will change it.

+   if (!qup->dma_rx)
+   return -EPROBE_DEFER;

Re: [PATCH 2/6] i2c: qup: Add V2 tags support

2015-03-25 Thread Sricharan R

Hi Ivan,

On 03/25/2015 05:54 PM, Ivan T. Ivanov wrote:


Hi Sricharan,

On Fri, 2015-03-13 at 23:19 +0530, Sricharan R wrote:

From: Andy Gross 

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 
Signed-off-by: Sricharan R 
---
  drivers/i2c/busses/i2c-qup.c | 342 ++-






+#define I2C_QUP_CLK_MAX_FREQ   340


unused?


Ok, will remove this.


+
  /* Status, Error flags */
  #define I2C_STATUS_WR_BUFFER_FULL  BIT(0)
  #define I2C_STATUS_BUS_ACTIVE  BIT(8)
@@ -99,6 +117,11 @@

  #define QUP_READ_LIMIT 256

+struct qup_i2c_config {
+   int tag_ver;
+   int max_freq;
+};
+


Do you really need this one. It is referenced only during probe,
but information contained in is already available by other means.


Ok, agree that this can be removed and the information can be fixed
for V1 version and same for the rest of the other versions. That would
need to use compatible check though.



  struct qup_i2c_dev {
 struct device*dev;
 void __iomem*base;
@@ -112,9 +135,20 @@ struct qup_i2c_dev {
 int in_fifo_sz;
 int out_blk_sz;
 int in_blk_sz;
-
+   int blocks;
+   u8  *block_tag_len;
+   int *block_data_len;


Maybe these could be organized in struct?


ok, will group it.





+static void qup_i2c_create_tag_v2(struct qup_i2c_dev *qup,
+   struct i2c_msg *msg)
+{
+   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->block_pos = 0;
+   qup->pos = 0;
+   qup->blocks = (msg->len + QUP_READ_LIMIT - 1) / (QUP_READ_LIMIT);


Braces around QUP_READ_LIMIT are not needed.


ok.

+   rem = msg->len % QUP_READ_LIMIT;
+
+   /* 2 tag bytes for each block + 2 extra bytes for first block */
+   qup->tags = kzalloc((qup->blocks << 1) + 2, GFP_KERNEL);


Don't play tricks with shifts, just use multiplication.


why ?

+   qup->block_tag_len = kzalloc(qup->blocks, GFP_KERNEL);
+   qup->block_data_len = kzalloc(sizeof(int) * qup->blocks, GFP_KERNEL);


Better use sizeof(*qup->block_data_len).


ok.

+
+   while (blocks < qup->blocks) {
+   /* 0 is used to specify a READ_LIMIT of 256 bytes */
+   data_len = (blocks < (qup->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;


Is this second QUP_TAG_V2_START intentional?


 Yes, for HS mode 2 start tags are required.

+   }
+
+   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->blocks - 1)) {
+   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->block_tag_len[blocks] = block_len;
+
+   if (!data_len)
+   qup->block_data_len[blocks] = QUP_READ_LIMIT;
+   else
+   qup->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->blocks << 1);


here again.


hmm, why not shift ?

+   else
+   qup->rx_tag_len = 0;

[PATCH 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts

2015-03-13 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 30 +++---
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 4dad23b..49c6cba 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -221,26 +221,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 +363,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, 0, 1);
 
 err:
disable_irq(qup->irq);
-- 
1.8.2.1

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


[PATCH 5/6] dts: msm8974: Add blsp2_bam dma node

2015-03-13 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi 
b/arch/arm/boot/dts/qcom-msm8974.dtsi
index e265ec1..3f648ae 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 {
+   compatible = "qcom,bam-v1.4.0";
+   reg = <0xf9944000 0x19000>;
+   interrupts = <0 239 0>;
+   clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+   clock-names = "bam_clk";
+   #dma-cells = <1>;
+   qcom,ee = <0>;
+   };
};
 };
-- 
1.8.2.1

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


[PATCH 3/6] i2c: qup: Add bam dma capabilities

2015-03-13 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 365 ++-
 1 file changed, 359 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index e4e223f..11ea6af 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -25,6 +25,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -34,6 +39,7 @@
 #define QUP_OPERATIONAL0x018
 #define QUP_ERROR_FLAGS0x01c
 #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
@@ -44,6 +50,7 @@
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
 #define QUP_I2C_MASTER_GEN 0x408
+#define QUP_I2C_MASTER_CONFIG  0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
@@ -53,6 +60,7 @@
 
 #define QUP_STATE_VALIDBIT(2)
 #define QUP_I2C_MAST_GEN   BIT(4)
+#define QUP_I2C_FLUSH  BIT(6)
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfc
@@ -78,7 +86,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_ENBIT(15)
 
@@ -105,6 +116,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  100
 #define I2C_QUP_CLK_MAX_FREQ   340
@@ -116,12 +131,21 @@
 #define QUP_STATUS_ERROR_FLAGS 0x7c
 
 #define QUP_READ_LIMIT 256
+#define MX_TX_RX_LEN   SZ_64K
+#define MX_BLOCKS  (MX_TX_RX_LEN / QUP_READ_LIMIT)
+
+#define TOUT_MAX   300 /* Max timeout for 32k tx/tx */
 
 struct qup_i2c_config {
int tag_ver;
int max_freq;
 };
 
+struct tag {
+   u8 *start;
+   dma_addr_t addr;
+};
+
 struct qup_i2c_dev {
struct device   *dev;
void __iomem*base;
@@ -157,9 +181,35 @@ struct qup_i2c_dev {
/* QUP core errors */
u32 qup_err;
 
+   /* dma parameters */
+   boolis_dma;
+   struct  dma_pool *dpool;
+   struct  tag start_tag;
+   struct  tag scratch_tag;
+   struct  tag footer_tag;
+   struct  dma_chan *dma_tx;
+   struct  dma_chan *dma_rx;
+   struct  scatterlist *sg_tx;
+   struct  scatterlist *sg_rx;
+   dma_addr_t  sg_tx_phys;
+   dma_addr_t  sg_rx_phys;
+
struct completion   xfer;
 };
 
+struct i2c_bam_xfer {
+   struct qup_i2c_dev *qup;
+   u32 start_len;
+
+   u32 rx_nents;
+   u32 tx_nents;
+
+   struct dma_async_tx_descriptor *tx_desc;
+   dma_cookie_t tx_cookie;
+   struct dma_async_tx_descriptor *rx_desc;
+   dma_cookie_t rx_cookie;
+};
+
 static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
 {
struct qup_i2c_dev *qup = dev;
@@ -233,6 +283,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);
@@ -719,12 +777,244 @@ err:
return ret;
 }
 
+static void bam_i2c_callback(void *data)
+{
+   struct qup_i2c_dev *qup = data;
+
+   complete(&qup->xfer);
+}
+
+static int get_start_tag(u8 *tag, struct i2c_msg *msg, int first, int last,
+   int blen)
+{
+   u8 addr = (msg->addr << 1) | ((msg->flags &

[PATCH 2/6] i2c: qup: Add V2 tags support

2015-03-13 Thread Sricharan R
From: Andy Gross 

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 
Signed-off-by: Sricharan R 
---
 drivers/i2c/busses/i2c-qup.c | 342 ++-
 1 file changed, 305 insertions(+), 37 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 49c6cba..e4e223f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* QUP Registers */
 #define QUP_CONFIG 0x000
@@ -42,6 +43,7 @@
 #define QUP_IN_FIFO_BASE   0x218
 #define QUP_I2C_CLK_CTL0x400
 #define QUP_I2C_STATUS 0x404
+#define QUP_I2C_MASTER_GEN 0x408
 
 /* QUP States and reset values */
 #define QUP_RESET_STATE0
@@ -69,6 +71,8 @@
 #define QUP_CLOCK_AUTO_GATEBIT(13)
 #define I2C_MINI_CORE  (2 << 8)
 #define I2C_N_VAL  15
+#define I2C_N_VAL_V2   7
+
 /* Most significant word offset in FIFO port */
 #define QUP_MSW_SHIFT  (I2C_N_VAL + 1)
 
@@ -80,17 +84,31 @@
 
 #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  100
+#define I2C_QUP_CLK_MAX_FREQ   340
+
 /* Status, Error flags */
 #define I2C_STATUS_WR_BUFFER_FULL  BIT(0)
 #define I2C_STATUS_BUS_ACTIVE  BIT(8)
@@ -99,6 +117,11 @@
 
 #define QUP_READ_LIMIT 256
 
+struct qup_i2c_config {
+   int tag_ver;
+   int max_freq;
+};
+
 struct qup_i2c_dev {
struct device   *dev;
void __iomem*base;
@@ -112,9 +135,20 @@ struct qup_i2c_dev {
int in_fifo_sz;
int out_blk_sz;
int in_blk_sz;
-
+   int blocks;
+   u8  *block_tag_len;
+   int *block_data_len;
+   int block_pos;
unsigned long   one_byte_t;
 
+   int is_hs;
+   booluse_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;
@@ -262,8 +296,13 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int 
op, bool val,
 
 static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg 
*msg)
 {
-   /* Number of entries to shift out, including the start */
-   int total = msg->len + 1;
+   /* Total Number of entries to shift out, including the tags */
+   int total;
+
+   if (qup->use_v2_tags)
+   total = msg->len + qup->tx_tag_len;
+   else
+   total = msg->len + 1; /* plus start tag */
 
if (total < qup->out_fifo_sz) {
/* FIFO mode */
@@ -277,7 +316,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;
@@ -318,6 +357,136 @@ static void qup_i2c_issue_write(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)
+{
+   u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD

[PATCH 4/6] i2c: qup: Transfer every i2c_msg in i2c_msgs without stop

2015-03-13 Thread Sricharan R
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 
---
 drivers/i2c/busses/i2c-qup.c | 192 ++-
 1 file changed, 115 insertions(+), 77 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 11ea6af..90a2b5e 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -846,75 +846,91 @@ void qup_sg_set_buf(struct scatterlist *sg, void *buf, 
struct tag *tg,
sg_dma_address(sg) = tg->addr + ((u8 *) buf - tg->start);
 }
 
-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->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->sg_rx[i << 1],
-  &qup->scratch_tag.start[0],
-  &qup->scratch_tag,
-  2, qup, 0, 0);
-
-   qup_sg_set_buf(&qup->sg_rx[(i << 1) + 1],
-  &msg->buf[QUP_READ_LIMIT * i],
-  NULL, tlen, qup, 1,
-  DMA_FROM_DEVICE);
-
-   i++;
-   }
-
-   sg_init_one(qup->sg_tx, &qup->start_tag.start[0], len);
-   qup_sg_set_buf(qup->sg_tx, &qup->start_tag.start[0],
-  &qup->start_tag, len, qup, 0, 0);
-   qup_sg_set_buf(&qup->sg_rx[i << 1],
-  &qup->scratch_tag.start[1],
-  &qup->scratch_tag, 2,
-  qup, 0, 0);
-   } else {
-   qup->footer_tag.start[0] = QUP_BAM_FLUSH_STOP;
-   qup->footer_tag.start[1] = QUP_BAM_FLUSH_STOP;
-
-   tx_nents = (blocks << 1) + 1;
-   sg_init_table(qup->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->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->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;
+
+  

[PATCH 6/6] dts: msm8974: Add dma channels for blsp2_i2c1 node

2015-03-13 Thread Sricharan R
Signed-off-by: Sricharan R 
---
 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 3f648ae..1ec7ec5 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 = "bam-tx", "bam-rx";
};
 
blsp2_dma: dma@f9944000 {
-- 
1.8.2.1

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


[PATCH 0/6] i2c: qup: Add support for v2 tags and bam dma

2015-03-13 Thread Sricharan R
QUP from version 2.1.1 onwards, supports a new format of
i2c command tags. Tag codes instructs the controller to
perform a operation like read/write. This new tagging version
supports 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

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 |  12 +
 drivers/i2c/busses/i2c-qup.c| 783 +---
 2 files changed, 741 insertions(+), 54 deletions(-)

-- 
1.8.2.1

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