From patchwork Tue Apr 15 07:25:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Barry Song <21cnbao@gmail.com> X-Patchwork-Id: 3989741 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B861ABFF02 for ; Tue, 15 Apr 2014 07:28:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CF6A0201DE for ; Tue, 15 Apr 2014 07:28:52 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D9D8620127 for ; Tue, 15 Apr 2014 07:28:51 +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 1WZxl3-0002lT-Lx; Tue, 15 Apr 2014 07:26:17 +0000 Received: from mail-pa0-f47.google.com ([209.85.220.47]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WZxl1-0002fp-2W for linux-arm-kernel@lists.infradead.org; Tue, 15 Apr 2014 07:26:15 +0000 Received: by mail-pa0-f47.google.com with SMTP id lj1so9277513pab.20 for ; Tue, 15 Apr 2014 00:25:51 -0700 (PDT) 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=084mw5c+VUPFUGQT/rjfhRoNsf1j1Ga6fDSndfCGgjY=; b=CCE1LxrVZ09U7SfaR6fuonkIXaH4N9Q+6+VGt1WmC9oht2ELXaCoMZ9hHAioJWmA4+ oyvLiwu9psjc7Z0eanS85IaOl4uoz2lOnzXsRYypj9gQVnLB41Ii8Mb7qfH2sT05oIig mHNLZsLulyPMx5NB4qV0LR03fxpjr+lpHz+kpyXGY5t07ekTgkI9A7IrT+nclHw646e3 N2O1Bqebi1CEZan1w4RXwSTuRZ2VP7KMyQV2RAWtB3zSe1uN/SZpgeqVJhk/nQZHlqKX g9l7/2dLfuNd6MLEuqqMZxlx/9Jz6ay84iMdJpswBGieLuog6Aql5n9F8qJszuYfXLR0 K8ow== X-Received: by 10.66.122.101 with SMTP id lr5mr224688pab.130.1397546751332; Tue, 15 Apr 2014 00:25:51 -0700 (PDT) Received: from barry-laptop.ROOT.PRI ([117.136.8.56]) by mx.google.com with ESMTPSA id v1sm38364625pbl.1.2014.04.15.00.25.41 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 15 Apr 2014 00:25:50 -0700 (PDT) From: Barry Song <21cnbao@gmail.com> To: broonie@kernel.org, linux-spi@vger.kernel.org Subject: [PATCH 2/2] spi: sirf: decrease the interrupt count and latency of PIO mode Date: Tue, 15 Apr 2014 15:25:00 +0800 Message-Id: <1397546700-21605-2-git-send-email-21cnbao@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1397546700-21605-1-git-send-email-21cnbao@gmail.com> References: <1397546700-21605-1-git-send-email-21cnbao@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140415_002615_154229_248588DD X-CRM114-Status: GOOD ( 16.14 ) X-Spam-Score: -0.8 (/) Cc: Qipan Li , workgroup.linux@csr.com, linux-arm-kernel@lists.infradead.org, Barry Song X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 From: Qipan Li orignal PIO tranfer method can described as follows: 1. fill one byte into txfifo 2. enable oflow/uflow/txfifo_empty/txfifo_thd/rxfifo_thd/rxfifo_full/ frm_end interrupt 3. isr process more than 7 interrupt signal, do data fill/fetch in isr 4. all bytes transfer done, end. current PIO tranfer method be described as follows: 1. fill as much as bytes but no more than 256 bytes(fifo size) 2. enable oflow/uflow/txfifo_empty interrupt 3. isr process 3 interrupt signal, do complete works. 4. after isr done, if there are left bytes go into 1 else go into 5 5. transfer end by current PIO transfer method: 1. reduce interrupt counts in spi interrupt line. 2. reduce interrupt latency because no do data fill/fetch in isr. Signed-off-by: Qipan Li Signed-off-by: Barry Song --- drivers/spi/spi-sirf.c | 103 ++++++++++++++++++++++++++---------------------- 1 files changed, 56 insertions(+), 47 deletions(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 2d23899..4fcb015 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -86,6 +86,7 @@ #define SIRFSOC_SPI_TX_DONE BIT(1) #define SIRFSOC_SPI_RX_OFLOW BIT(2) #define SIRFSOC_SPI_TX_UFLOW BIT(3) +#define SIRFSOC_SPI_RX_IO_DMA BIT(4) #define SIRFSOC_SPI_RX_FIFO_FULL BIT(6) #define SIRFSOC_SPI_TXFIFO_EMPTY BIT(7) #define SIRFSOC_SPI_RXFIFO_THD_REACH BIT(8) @@ -265,41 +266,34 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) { struct sirfsoc_spi *sspi = dev_id; u32 spi_stat = readl(sspi->base + SIRFSOC_SPI_INT_STATUS); - - writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS); - if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) { complete(&sspi->tx_done); writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_INT_MASK_ALL, + sspi->base + SIRFSOC_SPI_INT_STATUS); return IRQ_HANDLED; } /* Error Conditions */ if (spi_stat & SIRFSOC_SPI_RX_OFLOW || spi_stat & SIRFSOC_SPI_TX_UFLOW) { + complete(&sspi->tx_done); complete(&sspi->rx_done); writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_INT_MASK_ALL, + sspi->base + SIRFSOC_SPI_INT_STATUS); + return IRQ_HANDLED; } + if (spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY) + complete(&sspi->tx_done); + while (!(readl(sspi->base + SIRFSOC_SPI_INT_STATUS) & + SIRFSOC_SPI_RX_IO_DMA)) + cpu_relax(); + complete(&sspi->rx_done); + writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_INT_MASK_ALL, + sspi->base + SIRFSOC_SPI_INT_STATUS); - if (spi_stat & (SIRFSOC_SPI_FRM_END - | SIRFSOC_SPI_RXFIFO_THD_REACH)) - while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) - & SIRFSOC_SPI_FIFO_EMPTY)) && - sspi->left_rx_word) - sspi->rx_word(sspi); - - if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY | - SIRFSOC_SPI_TXFIFO_THD_REACH)) - while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) - & SIRFSOC_SPI_FIFO_FULL)) && - sspi->left_tx_word) - sspi->tx_word(sspi); - - /* Received all words */ - if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) { - complete(&sspi->rx_done); - writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); - } return IRQ_HANDLED; } @@ -420,32 +414,47 @@ static void spi_sirfsoc_pio_transfer(struct spi_device *spi, int timeout = t->len * 10; sspi = spi_master_get_devdata(spi->master); - writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); - writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); - writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); - writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); - writel(0, sspi->base + SIRFSOC_SPI_INT_EN); - writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); - writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | SIRFSOC_SPI_MUL_DAT_MODE | - SIRFSOC_SPI_ENA_AUTO_CLR, sspi->base + SIRFSOC_SPI_CTRL); - writel(sspi->left_tx_word - 1, - sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); - writel(sspi->left_rx_word - 1, - sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); - sspi->tx_word(sspi); - writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN | - SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_RXFIFO_THD_INT_EN | - SIRFSOC_SPI_TXFIFO_THD_INT_EN | SIRFSOC_SPI_FRM_END_INT_EN| - SIRFSOC_SPI_RXFIFO_FULL_INT_EN, - sspi->base + SIRFSOC_SPI_INT_EN); - writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, + for (;;) { + writel(SIRFSOC_SPI_FIFO_RESET, + sspi->base + SIRFSOC_SPI_RXFIFO_OP); + writel(SIRFSOC_SPI_FIFO_RESET, + sspi->base + SIRFSOC_SPI_TXFIFO_OP); + writel(SIRFSOC_SPI_FIFO_START, + sspi->base + SIRFSOC_SPI_RXFIFO_OP); + writel(SIRFSOC_SPI_FIFO_START, + sspi->base + SIRFSOC_SPI_TXFIFO_OP); + writel(0, sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_INT_MASK_ALL, + sspi->base + SIRFSOC_SPI_INT_STATUS); + writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | + SIRFSOC_SPI_MUL_DAT_MODE | SIRFSOC_SPI_ENA_AUTO_CLR, + sspi->base + SIRFSOC_SPI_CTRL); + writel(min(sspi->left_tx_word, (u32)(256 / sspi->word_width)) + - 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); + writel(min(sspi->left_rx_word, (u32)(256 / sspi->word_width)) + - 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); + while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) + & SIRFSOC_SPI_FIFO_FULL)) && sspi->left_tx_word) + sspi->tx_word(sspi); + writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN | + SIRFSOC_SPI_TX_UFLOW_INT_EN | + SIRFSOC_SPI_RX_OFLOW_INT_EN, + sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN); - if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) - dev_err(&spi->dev, "transfer timeout\n"); - writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); - writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); - writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); - writel(0, sspi->base + SIRFSOC_SPI_INT_EN); + if (!wait_for_completion_timeout(&sspi->tx_done, timeout) || + !wait_for_completion_timeout(&sspi->rx_done, timeout)) { + dev_err(&spi->dev, "transfer timeout\n"); + break; + } + while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) + & SIRFSOC_SPI_FIFO_EMPTY)) && sspi->left_rx_word) + sspi->rx_word(sspi); + writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); + writel(0, sspi->base + SIRFSOC_SPI_TXFIFO_OP); + if (sspi->left_tx_word == 0 && sspi->left_rx_word == 0) + break; + } } static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)