From patchwork Thu Mar 13 08:29:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cao Minh Hiep X-Patchwork-Id: 3822651 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E1FF29F1CD for ; Thu, 13 Mar 2014 08:36:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DE28A2028D for ; Thu, 13 Mar 2014 08:36:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DEF2920270 for ; Thu, 13 Mar 2014 08:36:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753295AbaCMIgI (ORCPT ); Thu, 13 Mar 2014 04:36:08 -0400 Received: from m119.secure.ne.jp ([158.199.161.240]:45681 "HELO m119.secure.ne.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1753277AbaCMIgG (ORCPT ); Thu, 13 Mar 2014 04:36:06 -0400 Received: (qmail 61927 invoked from network); 13 Mar 2014 17:29:25 +0900 Received: from unknown (HELO localhost) (61.118.107.10) by 0 with SMTP; 13 Mar 2014 17:29:25 +0900 From: Cao Minh Hiep To: broonie@kernel.org Cc: devicetree@vger.kernel.org, linux-sh@vger.kernel.org, kuninori.morimoto.gx@renesas.com, geert+renesas@linux-m68k.org Subject: [RFC] spi: Using Trigger number to transmit/receive data Date: Thu, 13 Mar 2014 17:29:24 +0900 Message-Id: <1394699364-5669-2-git-send-email-cm-hiep@jinso.co.jp> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1394699364-5669-1-git-send-email-cm-hiep@jinso.co.jp> References: <1394699364-5669-1-git-send-email-cm-hiep@jinso.co.jp> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 From: Hiep Cao Minh In order to transmit and receive data when have 32 bytes of data that ready has prepared on Transmit/Receive Buffer to transmit or receive. Instead transmits/receives a byte data using Transmit/Receive Buffer Data Triggering Number will improve the speed of transfer data. Signed-off-by: Hiep Cao Minh --- drivers/spi/spi-rspi.c | 144 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 124 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 28987d9..772a942 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -174,6 +174,12 @@ #define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset (qspi only) */ #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ +#define SPBFCR_TXTRG_31B 0x00 /* QSPI only */ +#define SPBFCR_TXTRG_0B 0x30 /* QSPI only */ +#define SPBFCR_RXTRG_1B 0x00 /* QSPI only */ +#define SPBFCR_RXTRG_32B 0x07 /* QSPI only */ + +#define QSPI_BUFFER_SIZE 32 #define DUMMY_DATA 0x00 @@ -224,6 +230,16 @@ static u16 rspi_read16(const struct rspi_data *rspi, u16 offset) return ioread16(rspi->addr + offset); } +static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) +{ + u8 data; + + data = rspi_read8(rspi, reg); + data &= ~mask; + data |= (val & mask); + rspi_write8(rspi, data, reg); +} + /* optional functions */ struct spi_ops { int (*set_config_register)(const struct rspi_data *rspi, @@ -358,6 +374,44 @@ static void rspi_negate_ssl(const struct rspi_data *rspi) rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR); } +static int qspi_set_send_trigger(struct rspi_data *rspi, int remain) +{ + int n; + + n = min(remain, QSPI_BUFFER_SIZE); + + if (remain >= QSPI_BUFFER_SIZE) { + /* sets triggering number to 32 bytes */ + qspi_update(rspi, SPBFCR_TXTRG_MASK, + SPBFCR_TXTRG_0B, QSPI_SPBFCR); + } else { + /* sets triggering number to 1 byte */ + qspi_update(rspi, SPBFCR_TXTRG_MASK, + SPBFCR_TXTRG_31B, QSPI_SPBFCR); + } + + return n; +} + +static int qspi_set_receive_trigger(struct rspi_data *rspi, int remain) +{ + int n; + + n = min(remain, QSPI_BUFFER_SIZE); + + if (remain >= QSPI_BUFFER_SIZE) { + /* sets triggering number to 32 bytes */ + qspi_update(rspi, SPBFCR_RXTRG_MASK, + SPBFCR_RXTRG_32B, QSPI_SPBFCR); + } else { + /* sets triggering number to 1 byte */ + qspi_update(rspi, SPBFCR_RXTRG_MASK, + SPBFCR_RXTRG_1B, QSPI_SPBFCR); + } + + return n; +} + static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, struct spi_transfer *t) { @@ -389,9 +443,10 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, { int remain = t->len; const u8 *data = t->tx_buf; + int i, n; rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR); - rspi_write8(rspi, 0x00, QSPI_SPBFCR); + rspi_write8(rspi, DUMMY_DATA, QSPI_SPBFCR); while (remain > 0) { @@ -400,16 +455,38 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg, "%s: tx empty timeout\n", __func__); return -ETIMEDOUT; } - rspi_write8(rspi, *data++, RSPI_SPDR); - - if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { - dev_err(&rspi->master->dev, - "%s: receive timeout\n", __func__); - return -ETIMEDOUT; + n = qspi_set_send_trigger(rspi, remain); + if (n >= QSPI_BUFFER_SIZE) { + for (i = 0; i < n; i++) + rspi_write8(rspi, *data++, RSPI_SPDR); + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, + SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + for (i = 0; i < n; i++) + rspi_read8(rspi, RSPI_SPDR); + } else { + for (i = 0; i < n; i++) { + if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, + SPCR_SPTIE) < 0) { + dev_err(&rspi->master->dev, + "%s: tx empty timeout\n", __func__); + return -ETIMEDOUT; + } + rspi_write8(rspi, *data++, RSPI_SPDR); + + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, + SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + rspi_read8(rspi, RSPI_SPDR); + } } - rspi_read8(rspi, RSPI_SPDR); - - remain--; + remain -= n; } /* Waiting for the last transmission */ @@ -603,6 +680,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, { int remain = t->len; u8 *data; + int i, n; qspi_receive_init(rspi); @@ -614,17 +692,43 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg, "%s: tx empty timeout\n", __func__); return -ETIMEDOUT; } - /* dummy write for generate clock */ - rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR); - - if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) { - dev_err(&rspi->master->dev, - "%s: receive timeout\n", __func__); - return -ETIMEDOUT; + n = qspi_set_receive_trigger(rspi, remain); + if (n >= QSPI_BUFFER_SIZE) { + /* dummy write for generate clock */ + for (i = 0; i < n; i++) + rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR); + + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, + SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + /* SPDR allows 8, 16 or 32-bit access */ + for (i = 0; i < n; i++) + *data++ = rspi_read8(rspi, RSPI_SPDR); + } else { + for (i = 0; i < n; i++) { + if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, + SPCR_SPTIE) < 0) { + dev_err(&rspi->master->dev, + "%s: tx empty timeout\n", __func__); + return -ETIMEDOUT; + } + /* dummy write for generate clock */ + rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR); + + if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, + SPCR_SPRIE) < 0) { + dev_err(&rspi->master->dev, + "%s: receive timeout\n", __func__); + return -ETIMEDOUT; + } + /* SPDR allows 8, 16 or 32-bit access */ + *data++ = rspi_read8(rspi, RSPI_SPDR); + } } - /* SPDR allows 8, 16 or 32-bit access */ - *data++ = rspi_read8(rspi, RSPI_SPDR); - remain--; + remain -= n; } return 0;