From patchwork Mon Nov 9 05:43:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liguo Zhang X-Patchwork-Id: 7581161 Return-Path: X-Original-To: patchwork-linux-mediatek@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 62DBDC05C6 for ; Mon, 9 Nov 2015 05:45:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7FE5820774 for ; Mon, 9 Nov 2015 05:45:12 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 877EE20701 for ; Mon, 9 Nov 2015 05:45:11 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZvfGR-0003aS-4n; Mon, 09 Nov 2015 05:45:11 +0000 Received: from [210.61.82.184] (helo=mailgw02.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZvfFt-0002oh-36; Mon, 09 Nov 2015 05:44:38 +0000 X-Listener-Flag: 11101 Received: from mtkhts09.mediatek.inc [(172.21.101.70)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 471565670; Mon, 09 Nov 2015 13:44:15 +0800 Received: from mhfsdcap03.mhfswrd (10.17.3.153) by mtkhts09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 14.3.181.6; Mon, 9 Nov 2015 13:44:13 +0800 From: Liguo Zhang To: Wolfram Sang Subject: [PATCH v2 2/2] i2c: mediatek: fix i2c multi transfer issue in high speed mode Date: Mon, 9 Nov 2015 13:43:59 +0800 Message-ID: <1447047839-5223-3-git-send-email-liguo.zhang@mediatek.com> X-Mailer: git-send-email 1.8.1.1.dirty In-Reply-To: <1447047839-5223-1-git-send-email-liguo.zhang@mediatek.com> References: <1447047839-5223-1-git-send-email-liguo.zhang@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151108_214437_346080_92714E8B X-CRM114-Status: GOOD ( 16.20 ) X-Spam-Score: -1.1 (-) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Xudong Chen , srv_heupstream@mediatek.com, Sascha Hauer , linux-kernel@vger.kernel.org, Liguo Zhang , linux-mediatek@lists.infradead.org, linux-i2c@vger.kernel.org, Matthias Brugger , Eddie Huang , linux-arm-kernel@lists.infradead.org Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For platform with auto restart support, when doing i2c multi transfer in high speed, for example, doing write-then-read transfer, the master code will occupy the first transfer, and the second transfer will be the read transfer, the write transfer will be discarded. So we should first send the master code, and then start i2c multi transfer. Signed-off-by: Liguo Zhang Reviewed-by: Eddie Huang --- drivers/i2c/busses/i2c-mt65xx.c | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index dc4aac6..249df86 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -53,6 +53,8 @@ #define I2C_FS_TIME_INIT_VALUE 0x1303 #define I2C_WRRD_TRANAC_VALUE 0x0002 #define I2C_RD_TRANAC_VALUE 0x0001 +#define I2C_TRAN_DEFAULT_VALUE 0x0001 +#define I2C_TRANAC_DEFAULT_VALUE 0x0001 #define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_RX 0x0001 @@ -365,6 +367,43 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk, return 0; } +static int mtk_i2c_send_master_code(struct mtk_i2c *i2c) +{ + int ret = 0; + + reinit_completion(&i2c->msg_complete); + + writew(I2C_CONTROL_RS | I2C_CONTROL_ACKERR_DET_EN | + I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN, + i2c->base + OFFSET_CONTROL); + + /* Clear interrupt status */ + writew(I2C_RS_TRANSFER | I2C_TRANSAC_COMP | I2C_HS_NACKERR | I2C_ACKERR, + i2c->base + OFFSET_INTR_STAT); + + /* Enable interrupt */ + writew(I2C_RS_TRANSFER | I2C_TRANSAC_COMP, i2c->base + + OFFSET_INTR_MASK); + + writew(I2C_TRAN_DEFAULT_VALUE, i2c->base + OFFSET_TRANSFER_LEN); + writew(I2C_TRANAC_DEFAULT_VALUE, i2c->base + OFFSET_TRANSAC_LEN); + + writew(I2C_TRANSAC_START | I2C_RS_MUL_CNFG, i2c->base + OFFSET_START); + + ret = wait_for_completion_timeout(&i2c->msg_complete, + i2c->adap.timeout); + + completion_done(&i2c->msg_complete); + + if (ret == 0) { + dev_dbg(i2c->dev, "send master code timeout.\n"); + mtk_i2c_init_hw(i2c); + return -ETIMEDOUT; + } + + return 0; +} + static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, int num, int left_num) { @@ -539,6 +578,12 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, } } + if (i2c->auto_restart && i2c->speed_hz > 400000) { + ret = mtk_i2c_send_master_code(i2c); + if (ret) + return ret; + } + while (left_num--) { if (!msgs->buf) { dev_dbg(i2c->dev, "data buffer is NULL.\n");