From patchwork Mon Apr 16 01:22:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Worsley X-Patchwork-Id: 898403 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=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Rt2G3ZJG"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40PVyn2Gqrz9s0b for ; Mon, 16 Apr 2018 11:24:01 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752623AbeDPBYA (ORCPT ); Sun, 15 Apr 2018 21:24:00 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:41139 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752552AbeDPBX7 (ORCPT ); Sun, 15 Apr 2018 21:23:59 -0400 Received: by mail-pg0-f68.google.com with SMTP id e2so3057601pgv.8 for ; Sun, 15 Apr 2018 18:23:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8YnxwMFTytIQ+9sf0JCuA4t+JvBiyVFDW7s65Rovx5Y=; b=Rt2G3ZJGg06etywxYGM9oKLjQaxop3vN9iydupg06YSonu++t8uAPubd1Sg97FH4JB iKWlKlxpGSpIm6QM9GACwVzv6y8PQwYtJLnFmS3jxfHIPvrGihHUyWxjsHlspdFJvrkK bDyOtSiBWjAL24tR+gKEOcLCPofS8zZ1vqvMsJi0pIoukrmFiUb3cYGSdez2/Er5t6jg yLLxBBYAsfuctnz93VsHlX6OfRLyZimUQDAVonF2wtXn2xKZ+Mj0UXnFmXxAtldcWJGM TcUsAEQT6ZNn/UU6629jJzzcA/lB6HI5uxtXusHLyuG6xXNsRxcdolLJ3ZqC9wLPGRbn pa/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8YnxwMFTytIQ+9sf0JCuA4t+JvBiyVFDW7s65Rovx5Y=; b=Ouxa4YVI2KrIlzwVKYLtk5BngvDeC+VPg0l7tqRmmb+wp1JsTDELTTMAwC2GO6ORjm 8RqdCKiisxMI5hQSMU2MFnWOl6sjOekbPyfyLQNbBJy3FtVPjilbV2PCFu93BByBsVv9 NuNJgrwCIvPHx/Z3UaVrbBsgHC57TRPTCIkxY0kyx5Huf9CXodAtA4mCv3FR9IRpRuts 9wSceVNNjLOdMB0MwdXocDIKNn2aYSdHPB5AbResMAos4P2EzDYMOQ2D3QucROtwLYlc T0COmSQMj9zxGWMSgF4R5LxoBCc/H8L1wVj9gTpueriSmAeBLj3x1JX+YScuZR9a6FMV 0rLA== X-Gm-Message-State: ALQs6tDPd93xOEj9VJQj6Qo91loMxppsipNxj24ddKCpOAi2TB1Ykcnk p91tDHZ34utQ+eS28olqevg= X-Google-Smtp-Source: AIpwx48dnJK1a6pMC7x5PllG6y1+bka5RiC7NTCQY3+g5jLFoLLKwXmUag34urP3HyHsNyjsrijeBw== X-Received: by 10.101.97.200 with SMTP id j8mr11288075pgv.443.1523841838924; Sun, 15 Apr 2018 18:23:58 -0700 (PDT) Received: from localhost ([203.176.111.62]) by smtp.gmail.com with ESMTPSA id k66sm3477307pgk.24.2018.04.15.18.23.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 15 Apr 2018 18:23:58 -0700 (PDT) From: Andrew Worsley To: harinik@xilinx.com, APANDEY@xilinx.com, asarkar@xilinx.com, soren.brinkmann@xilinx.com, linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org Cc: Andrew Worsley Subject: [PATCH] Further cadence i2c buffer overrun fixes Date: Mon, 16 Apr 2018 11:22:48 +1000 Message-Id: <20180416012248.25891-2-amworsley@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180416012248.25891-1-amworsley@gmail.com> References: <20180416012248.25891-1-amworsley@gmail.com> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org After this set of changes ran over 2 days 17 hours with no i2c failures at 200kHz. Previously would lock up with BA (Bus Active) bit set continously with in a few hours Set the transfer size register *before* triggering the operation by setting the i2c address register with the slave address. If the transfer is less than one FIFO length clear the hold bit before starting the transfer by writing to the i2c address register. Finally for transfer larger than a FIFO in size clear the hold bit just before removing the byte that allows the rest of the transfer to fit into the FIFO and then complete. --- drivers/i2c/busses/i2c-cadence.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 925f77dfded8..260bd6c67e1f 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -449,10 +449,10 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) break; } - *(id->p_recv_buf)++ = - cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); if (check_hold && id->recv_count == CDNS_I2C_FIFO_DEPTH + 1) cdns_i2c_clear_bus_hold(id); + *(id->p_recv_buf)++ = + cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); id->recv_count--; id->curr_recv_count--; @@ -492,10 +492,6 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) } else if (id->recv_count && !hold_quirk && !id->curr_recv_count) { - /* Set the slave address in address register*/ - cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, - CDNS_I2C_ADDR_OFFSET); - if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) { cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE, CDNS_I2C_XFER_SIZE_OFFSET); @@ -505,6 +501,10 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) CDNS_I2C_XFER_SIZE_OFFSET); id->curr_recv_count = id->recv_count; } + + /* write the address register - triggers operation */ + cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); } /* Clear hold (if not repeated start) and signal completion */ @@ -661,15 +661,15 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) cdns_i2c_writereg(id->recv_count, CDNS_I2C_XFER_SIZE_OFFSET); } - /* Set the slave address in address register - triggers operation */ - cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); - cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, - CDNS_I2C_ADDR_OFFSET); /* Clear the bus hold flag if bytes to receive is less than FIFO size */ if (!id->bus_hold_flag && ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) cdns_i2c_clear_bus_hold(id); + /* Set the slave address in address register - triggers operation */ + cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); + cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); } /**