From patchwork Wed Feb 12 16:30:18 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: 3639111 X-Patchwork-Delegate: broonie@sirena.org.uk Return-Path: X-Original-To: patchwork-linux-spi@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 8D4BFBF13A for ; Wed, 12 Feb 2014 16:30:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 882C3201ED for ; Wed, 12 Feb 2014 16:30:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A5BF9201EC for ; Wed, 12 Feb 2014 16:30:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752587AbaBLQag (ORCPT ); Wed, 12 Feb 2014 11:30:36 -0500 Received: from mail-pa0-f52.google.com ([209.85.220.52]:34075 "EHLO mail-pa0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752228AbaBLQaf (ORCPT ); Wed, 12 Feb 2014 11:30:35 -0500 Received: by mail-pa0-f52.google.com with SMTP id bj1so9418024pad.11 for ; Wed, 12 Feb 2014 08:30:33 -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; bh=iTWswzzNGqr/0QE5Bh9KjBB0vrDuZXZ3tiZ5NI8NXWM=; b=yBLuqhLFykJidYFCMhBcq9xFyrOvtJsicaxZsfU4Osmxp+O6Mu31WCndSQpZkVaPY4 m0T9ydcKoINitvtLqnaj74fNxIitoEx/HB87P8Vdzw2UUIUBjQCjMMlVBcLIGz5ZyZgq bXCio5LYhVzYPnvbc5euTuQhOfBmaOcZzvdGJ+3VpmrFvMvwY1KSjyRb5q9/jAzLd2+R u+im/HU9M/MzbGcxXHoUBEc2st82L+sjiQLGn0dmoSRbnnksM9Zb9F8dA8Bsbdlg+49r sKD+bxTPELJ6kOm+E95/V6SUp2U/mFHKPfmADezYNYxIn2myeqSqJaUgUfpkJ1O5tHJC zbvw== X-Received: by 10.68.113.68 with SMTP id iw4mr18716608pbb.119.1392222633589; Wed, 12 Feb 2014 08:30:33 -0800 (PST) Received: from localhost.localdomain ([101.44.43.128]) by mx.google.com with ESMTPSA id pe3sm65109259pbc.23.2014.02.12.08.30.30 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 12 Feb 2014 08:30:32 -0800 (PST) From: Barry Song <21cnbao@gmail.com> To: broonie@kernel.org, linux-spi@vger.kernel.org Cc: workgroup.linux@csr.com, Qipan Li , Barry Song Subject: [PATCH 1/3] spi: sirf: provide a shortcut for spi command-data mode Date: Thu, 13 Feb 2014 00:30:18 +0800 Message-Id: <1392222620-17273-1-git-send-email-21cnbao@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, 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 there are many SPI clients which use the following protocal: step 1: send command bytes to clients(rx buffer is empty) step 2: send data bytes to clients or receive data bytes from clients. SiRFprimaII provides a shortcut for this kind of SPI transfer. when tx buf is less or equal than 4 bytes and rx buf is null in a transfer, we think it as 'command' data and use hardware command register for the transfer. here we can save some CPU loading than doing both tx and rx for a normal transfer. Signed-off-by: Qipan Li Signed-off-by: Barry Song --- drivers/spi/spi-sirf.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index e430689..c400ab7 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -132,6 +132,7 @@ #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \ ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) +#define SIRFSOC_MAX_CMD_BYTES 4 struct sirfsoc_spi { struct spi_bitbang bitbang; struct completion rx_done; @@ -161,7 +162,7 @@ struct sirfsoc_spi { dma_addr_t dst_start; void *dummypage; int word_width; /* in bytes */ - + bool tx_by_cmd; int chipselect[0]; }; @@ -260,6 +261,11 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) 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); + return IRQ_HANDLED; + } /* Error Conditions */ if (spi_stat & SIRFSOC_SPI_RX_OFLOW || spi_stat & SIRFSOC_SPI_TX_UFLOW) { @@ -310,6 +316,32 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); + if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) { + const u32 *cmd_ptr; + u32 cmd; + sspi->tx_by_cmd = true; + cmd_ptr = sspi->tx; + cmd = *cmd_ptr; + if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST)) + cmd = cpu_to_be32(cmd) >> + ((SIRFSOC_MAX_CMD_BYTES - t->len) * 8); + if (sspi->word_width == 2 && t->len == 4 && + (!(spi->mode & SPI_LSB_FIRST))) + cmd = ((cmd & 0xffff) << 16) | (cmd >> 16); + writel(cmd, sspi->base + SIRFSOC_SPI_CMD); + + writel(SIRFSOC_SPI_FRM_END_INT_EN, + sspi->base + SIRFSOC_SPI_INT_EN); + writel(SIRFSOC_SPI_CMD_TX_EN, + sspi->base + SIRFSOC_SPI_TX_RX_EN); + + if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { + dev_err(&spi->dev, "transfer timeout\n"); + return 0; + } + return t->len; + } else + sspi->tx_by_cmd = false; if (sspi->left_tx_word == 1) { writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | SIRFSOC_SPI_ENA_AUTO_CLR, @@ -519,6 +551,11 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL); writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); + if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) + regval |= (SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) | + SIRFSOC_SPI_CMD_MODE); + else + regval &= ~SIRFSOC_SPI_CMD_MODE; writel(regval, sspi->base + SIRFSOC_SPI_CTRL); if (IS_DMA_VALID(t)) {