From patchwork Fri Nov 27 23:16:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Bondarenko X-Patchwork-Id: 7715651 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4DCBD9F7CA for ; Fri, 27 Nov 2015 23:17:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 69AC920684 for ; Fri, 27 Nov 2015 23:17:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3072F20680 for ; Fri, 27 Nov 2015 23:17:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750768AbbK0XQ5 (ORCPT ); Fri, 27 Nov 2015 18:16:57 -0500 Received: from mail-lf0-f41.google.com ([209.85.215.41]:33713 "EHLO mail-lf0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750858AbbK0XQM (ORCPT ); Fri, 27 Nov 2015 18:16:12 -0500 Received: by lfaz4 with SMTP id z4so142470314lfa.0; Fri, 27 Nov 2015 15:16:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Hqb2ZpJ/y584osUQnYDCKlPBvijaoqORM3qtFwBNNHk=; b=DIFEhXcD4P3CI4T/avyK4a9fVywCcbzBZoy5jJmFTkB5TmiD+BzL9jOFEsyn+yDx3e HOrgssSAUuUcATdY9QsRe3+qEZpKsWR1TdOvGbzYeWURNlJ2jPg5Kw7w56p0aCMqzMYX 70eE/u8HniFbsbF5qtLVAcI7Apr1AD/XIEXt2jDWA8th20i+zmtDtX1B2B7OLrBJjk90 moOF7ywdLg7VCszeNAUiVPyo0/MtHvgirnXgZ0OvIWkMyUfOGy3+T7UGqjNedxpMYDjA AiADlm/jqwazkllHjdkW0KlxBZB1Be/OyHn6PMc1loMX+lig2ceNu93ZAyWMXvrDqB8h 1PBg== X-Received: by 10.25.168.140 with SMTP id r134mr22352439lfe.34.1448666170495; Fri, 27 Nov 2015 15:16:10 -0800 (PST) Received: from localhost.localdomain (c-89-233-200-205.cust.bredband2.com. [89.233.200.205]) by smtp.gmail.com with ESMTPSA id ru9sm254625lbb.3.2015.11.27.15.16.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 27 Nov 2015 15:16:09 -0800 (PST) From: Anton Bondarenko To: broonie@kernel.org, b38343@freescale.com, s.hauer@pengutronix.de Cc: linux-kernel@vger.kernel.org, linux-spi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, vladimir_zapolskiy@mentor.com, jiada_wang@mentor.com Subject: [PATCH v4 2/7] spi: imx: replace fixed timeout with calculated one Date: Sat, 28 Nov 2015 00:16:00 +0100 Message-Id: <1448666165-7473-3-git-send-email-anton.bondarenko.sama@gmail.com> X-Mailer: git-send-email 2.6.3 In-Reply-To: <1448666165-7473-1-git-send-email-anton.bondarenko.sama@gmail.com> References: <1448666165-7473-1-git-send-email-anton.bondarenko.sama@gmail.com> Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_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 Fixed timeout value can fire while transaction is ongoing. This may happen because there are no strict requirements on SPI transaction duration. Dynamic timeout value is generated based on SCLK and transaction size. There is also 4 * SCLK delay between TX bursts related to CS change. Signed-off-by: Anton Bondarenko --- drivers/spi/spi-imx.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bd7b721..4770d81 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -57,7 +57,6 @@ /* The maximum bytes that a sdma BD can transfer.*/ #define MAX_SDMA_BD_BYTES (1 << 15) -#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000)) struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; @@ -93,6 +92,7 @@ struct spi_imx_data { struct clk *clk_per; struct clk *clk_ipg; unsigned long spi_clk; + unsigned int spi_bus_clk; unsigned int count; void (*tx)(struct spi_imx_data *); @@ -314,8 +314,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, { u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); - - u32 clk = config->speed_hz, delay; + u32 delay; /* * The hardware seems to have a race condition when changing modes. The @@ -327,7 +326,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, ctrl |= MX51_ECSPI_CTRL_MODE_MASK; /* set clock speed */ - ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk); + spi_imx->spi_bus_clk = config->speed_hz; + ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, + &spi_imx->spi_bus_clk); /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(config->cs); @@ -367,7 +368,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, * the SPI communication as the device on the other end would consider * the change of SCLK polarity as a clock tick already. */ - delay = (2 * 1000000) / clk; + delay = (2 * USEC_PER_SEC) / spi_imx->spi_bus_clk; if (likely(delay < 10)) /* SCLK is faster than 100 kHz */ udelay(delay); else /* SCLK is _very_ slow */ @@ -890,12 +891,27 @@ static void spi_imx_dma_tx_callback(void *cookie) complete(&spi_imx->dma_tx_completion); } +static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size) +{ + unsigned long timeout = 0; + + /* Time with actual data transfer and CS change delay related to HW */ + timeout = (8 + 4) * size / spi_imx->spi_bus_clk; + + /* Add extra second for scheduler related activities */ + timeout += 1; + + /* Double calculated timeout */ + return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC); +} + static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, struct spi_transfer *transfer) { struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; int ret; unsigned long timeout; + unsigned long transfer_timeout; const int left = transfer->len % spi_imx->wml; struct spi_master *master = spi_imx->bitbang.master; struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; @@ -956,9 +972,11 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dma_async_issue_pending(master->dma_tx); spi_imx->devtype_data->trigger(spi_imx); + transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len); + /* Wait SDMA to finish the data transfer.*/ timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, - IMX_DMA_TIMEOUT); + transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA TX\n", dev_driver_string(&master->dev), @@ -966,8 +984,10 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); } else { + transfer_timeout = spi_imx_calculate_timeout(spi_imx, + spi_imx->wml); timeout = wait_for_completion_timeout( - &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); + &spi_imx->dma_rx_completion, transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA RX\n", dev_driver_string(&master->dev), @@ -989,7 +1009,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN); timeout = wait_for_completion_timeout( - &spi_imx->xfer_done, IMX_DMA_TIMEOUT); + &spi_imx->xfer_done, transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in RX tail\n", dev_driver_string(&master->dev),