From patchwork Tue Jan 19 10:02:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 8059671 Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id ABC00BEEE5 for ; Tue, 19 Jan 2016 10:05:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B6CCC2037C for ; Tue, 19 Jan 2016 10:05:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 96AA320120 for ; Tue, 19 Jan 2016 10:05:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932808AbcASKE5 (ORCPT ); Tue, 19 Jan 2016 05:04:57 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:59504 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932840AbcASKDE (ORCPT ); Tue, 19 Jan 2016 05:03:04 -0500 Received: from smtp.codeaurora.org (localhost [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id F21236061B; Tue, 19 Jan 2016 10:03:03 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E3D1560577; Tue, 19 Jan 2016 10:03:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from blr-ubuntu-32.ap.qualcomm.com (unknown [202.46.23.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: sricharan@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id ACBFF60377; Tue, 19 Jan 2016 10:02:58 +0000 (UTC) From: Sricharan R To: wsa@the-dreams.de Cc: devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, agross@codeaurora.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, iivanov@mm-sol.com, galak@codeaurora.org, dmaengine@vger.kernel.org, linux-arm-kernel@lists.infradead.org, andy.gross@linaro.org, ntelkar@codeaurora.org, sricharan@codeaurora.org, architt@codeaurora.org Subject: [PATCH V7 1/6] i2c: qup: Change qup_wait_writeready function to use for all timeouts Date: Tue, 19 Jan 2016 15:32:41 +0530 Message-Id: <1453197766-18976-2-git-send-email-sricharan@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1453197766-18976-1-git-send-email-sricharan@codeaurora.org> References: <1453197766-18976-1-git-send-email-sricharan@codeaurora.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Andy Gross Tested-by: Archit Taneja Tested-by: Telkar Nagender --- 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_BIT 0x1 +#define RESET_BIT 0x0 +#define ONE_BYTE 0x1 struct qup_i2c_dev { struct device *dev; @@ -221,26 +224,42 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state) return 0; } -static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup) +/** + * qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path + * @qup: The qup_i2c_dev device + * @op: The bit/event to wait on + * @val: value of the bit to wait on, 0 or 1 + * @len: The length the bytes to be transferred + */ +static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val, + int len) { unsigned long timeout; u32 opflags; u32 status; + u32 shift = __ffs(op); - timeout = jiffies + HZ; + len *= qup->one_byte_t; + /* timeout after a wait of twice the max time */ + timeout = jiffies + len * 4; for (;;) { opflags = readl(qup->base + QUP_OPERATIONAL); status = readl(qup->base + QUP_I2C_STATUS); - if (!(opflags & QUP_OUT_NOT_EMPTY) && - !(status & I2C_STATUS_BUS_ACTIVE)) - return 0; + if (((opflags & op) >> shift) == val) { + if (op == QUP_OUT_NOT_EMPTY) { + if (!(status & I2C_STATUS_BUS_ACTIVE)) + return 0; + } else { + return 0; + } + } if (time_after(jiffies, timeout)) return -ETIMEDOUT; - usleep_range(qup->one_byte_t, qup->one_byte_t * 2); + usleep_range(len, len * 2); } } @@ -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_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) { - u32 opflags; u32 val = 0; int idx; + int ret = 0; for (idx = 0; qup->pos < msg->len; idx++) { if ((idx & 1) == 0) { /* Check that FIFO have data */ - opflags = readl(qup->base + QUP_OPERATIONAL); - if (!(opflags & QUP_IN_NOT_EMPTY)) - break; + ret = qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, + SET_BIT, 4 * ONE_BYTE); + if (ret) + return ret; /* Reading 2 words at time */ val = readl(qup->base + QUP_IN_FIFO_BASE); @@ -405,6 +430,8 @@ static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; } } + + return ret; } static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) @@ -450,7 +477,9 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) goto err; } - qup_i2c_read_fifo(qup, msg); + ret = qup_i2c_read_fifo(qup, msg); + if (ret) + goto err; } while (qup->pos < msg->len); err: