From patchwork Thu Jan 4 17:37:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: dann frazier X-Patchwork-Id: 855739 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3zCFPJ2dcXz9s7F; Fri, 5 Jan 2018 04:37:40 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1eX9SS-0001z8-1p; Thu, 04 Jan 2018 17:37:36 +0000 Received: from complete.lackof.org ([198.49.126.79]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1eX9SQ-0001yx-55 for kernel-team@lists.ubuntu.com; Thu, 04 Jan 2018 17:37:34 +0000 Received: from localhost (c-73-217-118-12.hsd1.co.comcast.net [73.217.118.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by complete.lackof.org (Postfix) with ESMTPSA id CA69C33E0071 for ; Thu, 4 Jan 2018 10:37:32 -0700 (MST) Date: Thu, 4 Jan 2018 10:37:32 -0700 From: dann frazier To: kernel-team@lists.ubuntu.com Subject: [RESEND][PATCH 3/3][SRU Artful] i2c: xlp9xx: Handle I2C_M_RECV_LEN in msg->flags Message-ID: <20180104173732.GG5311@xps13.dannf> References: <20171213213516.11017-1-dann.frazier@canonical.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20171213213516.11017-1-dann.frazier@canonical.com> X-Mailer: git-send-email 2.15.1 User-Agent: Mutt/1.9.2 (2017-12-15) X-Virus-Scanned: clamav-milter 0.99.2 at complete.lackof.org X-Virus-Status: Clean X-Spam-Status: No, score=0.2 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on complete.lackof.org X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Kamlakant Patel BugLink: https://bugs.launchpad.net/bugs/1738073 The driver needs to handle the flag I2C_M_RECV_LEN during receive to support SMBus emulation. Update receive logic to handle the case where the length is received as the first byte of a transaction. Also update the code to handle I2C_CLIENT_PEC, which is set when the client sends a packet error checking code byte. Signed-off-by: Jayachandran C Signed-off-by: Kamlakant Patel Reviewed-by: Mika Westerberg Signed-off-by: Wolfram Sang (cherry picked from commit 5515ae112172e20667f02b16f45fbf992923dcb0) Signed-off-by: dann frazier --- drivers/i2c/busses/i2c-xlp9xx.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index f0bef2d5306c..b970bf8f38e5 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -82,6 +82,8 @@ struct xlp9xx_i2c_dev { struct completion msg_complete; int irq; bool msg_read; + bool len_recv; + bool client_pec; u32 __iomem *base; u32 msg_buf_remaining; u32 msg_len; @@ -143,10 +145,25 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv) static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) { u32 len, i; - u8 *buf = priv->msg_buf; + u8 rlen, *buf = priv->msg_buf; len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & XLP9XX_I2C_FIFO_WCNT_MASK; + if (!len) + return; + if (priv->len_recv) { + /* read length byte */ + rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); + *buf++ = rlen; + len--; + if (priv->client_pec) + ++rlen; + /* update remaining bytes and message length */ + priv->msg_buf_remaining = rlen; + priv->msg_len = rlen + 1; + priv->len_recv = false; + } + len = min(priv->msg_buf_remaining, len); for (i = 0; i < len; i++, buf++) *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); @@ -230,7 +247,7 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, int last_msg) { unsigned long timeleft; - u32 intr_mask, cmd, val; + u32 intr_mask, cmd, val, len; priv->msg_buf = msg->buf; priv->msg_buf_remaining = priv->msg_len = msg->len; @@ -263,9 +280,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, else val &= ~XLP9XX_I2C_CTRL_ADDMODE; + priv->len_recv = msg->flags & I2C_M_RECV_LEN; + len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len; + priv->client_pec = msg->flags & I2C_CLIENT_PEC; + /* set data length to be transferred */ val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) | - (msg->len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); + (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val); /* fill fifo during tx */ @@ -312,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, return -ETIMEDOUT; } + /* update msg->len with actual received length */ + if (msg->flags & I2C_M_RECV_LEN) + msg->len = priv->msg_len; return 0; }