From patchwork Tue Jul 3 14:37:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shubhrajyoti Datta X-Patchwork-Id: 1151861 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id E43F23FE80 for ; Tue, 3 Jul 2012 15:20:27 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Sm4n8-0005GG-RM; Tue, 03 Jul 2012 15:13:28 +0000 Received: from comal.ext.ti.com ([198.47.26.152]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Sm4HJ-00051T-Aw for linux-arm-kernel@lists.infradead.org; Tue, 03 Jul 2012 14:41:10 +0000 Received: from dbdp20.itg.ti.com ([172.24.170.38]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id q63Ec7TD028944; Tue, 3 Jul 2012 09:38:07 -0500 Received: from DBDE70.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id q63Ec43d012781; Tue, 3 Jul 2012 20:08:06 +0530 (IST) Received: from dbdp32.itg.ti.com (172.24.170.251) by dbde70.ent.ti.com (172.24.170.148) with Microsoft SMTP Server id 14.1.323.3; Tue, 3 Jul 2012 20:08:06 +0530 Received: from ula0393217.india.ti.com (smtpvbd.itg.ti.com [172.24.170.250]) by dbdp32.itg.ti.com (8.13.8/8.13.8) with ESMTP id q63Ec0El005725; Tue, 3 Jul 2012 20:08:06 +0530 From: Shubhrajyoti D To: Subject: [PATCHv4 16/18] i2c: omap: resize fifos before each message Date: Tue, 3 Jul 2012 20:07:54 +0530 Message-ID: <1341326276-25434-17-git-send-email-shubhrajyoti@ti.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1341326276-25434-1-git-send-email-shubhrajyoti@ti.com> References: <1341326276-25434-1-git-send-email-shubhrajyoti@ti.com> MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -6.9 (------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-6.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [198.47.26.152 listed in list.dnswl.org] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: tony@atomide.com, w.sang@pengutronix.de, Felipe Balbi , linux-i2c@vger.kernel.org, ben-linux@fluff.org, Shubhrajyoti D , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Felipe Balbi This patch will try to avoid the usage of draining feature by reconfiguring the FIFO the start condition of each message based on the message's size. By doing that, we will be better utilizing the FIFO when doing big transfers. While at that also drop the now uneeded check for dev->buf_len as we always know the amount of data to be transmitted. Signed-off-by: Felipe Balbi Signed-off-by: Shubhrajyoti D --- drivers/i2c/busses/i2c-omap.c | 83 +++++++++++++++++++++++++---------------- 1 files changed, 51 insertions(+), 32 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 5e3fb4c..f64916f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -190,6 +190,7 @@ struct omap_i2c_dev { u8 *regs; size_t buf_len; struct i2c_adapter adapter; + u8 threshold; u8 fifo_size; /* use as flag and value * fifo_size==0 implies no fifo * if set, should be trsh+1 @@ -415,13 +416,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); - if (dev->fifo_size) { - /* Note: setup required fifo size - 1. RTRSH and XTRSH */ - buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR | - (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR; - omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); - } - /* Take the I2C module out of reset: */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); @@ -482,6 +476,45 @@ static int omap_i2c_bus_clear(struct omap_i2c_dev *dev) return omap_i2c_wait_for_bb(dev); } +static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) +{ + u16 buf; + + if (dev->flags & OMAP_I2C_FLAG_NO_FIFO) + return; + + /* + * Set up notification threshold based on message size. We're doing + * this to try and avoid draining feature as much as possible. Whenever + * we have big messages to transfer (bigger than our total fifo size) + * then we might use draining feature to transfer the remaining bytes. + */ + + dev->threshold = clamp(size, (u8) 1, dev->fifo_size); + + buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG); + + if (is_rx) { + /* Clear RX Threshold */ + buf &= ~(0x3f << 8); + buf |= ((dev->threshold - 1) << 8) | OMAP_I2C_BUF_RXFIF_CLR; + } else { + /* Clear TX Threshold */ + buf &= ~0x3f; + buf |= (dev->threshold - 1) | OMAP_I2C_BUF_TXFIF_CLR; + } + + omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); + + if (dev->rev < OMAP_I2C_REV_ON_3630_4430) + dev->b_hw = 1; /* Enable hardware fixes */ + + /* calculate wakeup latency constraint for MPU */ + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->threshold) / + (1000 * dev->speed / 8); +} + /* * Low level master read/write transaction. */ @@ -498,6 +531,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, if (msg->len == 0) return -EINVAL; + dev->receiver = !!(msg->flags & I2C_M_RD); + omap_i2c_resize_fifo(dev, msg->len, dev->receiver); + omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr); /* REVISIT: Could the STB bit of I2C_CON be used with probing? */ @@ -513,7 +549,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, INIT_COMPLETION(dev->cmd_complete); dev->cmd_err = 0; - dev->receiver = !!(msg->flags & I2C_M_RD); w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; @@ -779,12 +814,6 @@ static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes, u16 w; while (num_bytes--) { - if (!dev->buf_len) { - dev_err(dev->dev, "%s without data", - is_rdr ? "RDR" : "RRDY"); - break; - } - w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); *dev->buf++ = w; dev->buf_len--; @@ -794,10 +823,8 @@ static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes, * omap4 is 8 bit wide */ if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) { - if (dev->buf_len) { - *dev->buf++ = w >> 8; - dev->buf_len--; - } + *dev->buf++ = w >> 8; + dev->buf_len--; } } } @@ -808,12 +835,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes, u16 w; while (num_bytes--) { - if (!dev->buf_len) { - dev_err(dev->dev, "%s without data", - is_xdr ? "XDR" : "XRDY"); - break; - } - w = *dev->buf++; dev->buf_len--; @@ -822,10 +843,8 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes, * omap4 is 8 bit wide */ if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) { - if (dev->buf_len) { - w |= *dev->buf++ << 8; - dev->buf_len--; - } + w |= *dev->buf++ << 8; + dev->buf_len--; } if (dev->errata & I2C_OMAP_ERRATA_I462) { @@ -920,8 +939,8 @@ complete: if (stat & OMAP_I2C_STAT_RRDY) { u8 num_bytes = 1; - if (dev->fifo_size) - num_bytes = dev->fifo_size; + if (dev->threshold) + num_bytes = dev->threshold; omap_i2c_receive_data(dev, num_bytes, false); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); @@ -948,8 +967,8 @@ complete: u8 num_bytes = 1; int ret; - if (dev->fifo_size) - num_bytes = dev->fifo_size; + if (dev->threshold) + num_bytes = dev->threshold; ret = omap_i2c_transmit_data(dev, num_bytes, false); stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);