From patchwork Thu May 30 05:52:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajeshwari Shinde X-Patchwork-Id: 17286 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f72.google.com (mail-yh0-f72.google.com [209.85.213.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8F14825D81 for ; Thu, 30 May 2013 05:49:58 +0000 (UTC) Received: by mail-yh0-f72.google.com with SMTP id f73sf4914575yha.11 for ; Wed, 29 May 2013 22:49:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:x-auditid:from:to:cc:subject:date:message-id:x-mailer :x-brightmail-tracker:x-brightmail-tracker:dlp-filter:x-mtr :x-cfilter-loop:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=nqcnmD7nDw6ro2DFAXW29hVx/ykT/D00bUT4J1woTRs=; b=VpTVsmEzLx6F55b6pexoDUEUen0KF/+r9f0lGtpG3AoWukEZuFYVeBXHuwlPzZtv/n 5gS86m2pYoAUrnI/4f7SaLJgPq045xVzupHfFABg2y9nwqTz7LhbjFvPSRTtBo1jmr0w KE/f+mDxnu9nkuJgvfwW2FEYMturxVYPCS5Mgrd774KOKUxiH3ZXOzt5y+J5ymPF2rF1 5q2sQ0XUscoOPRGO0FxdK+bmKJPI6M/J1SEBSXey4u4k/NZgm8n6FW+oC0pIzf61RcyN YG0rU5KTpf22ON+pEoKMmlcH6KxUerGIuYAlbe0vjNV90LMAoXkcXa+cQpPcGb1H2u4h m54Q== X-Received: by 10.224.42.141 with SMTP id s13mr3492200qae.3.1369892997975; Wed, 29 May 2013 22:49:57 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.131.71 with SMTP id ok7ls263604qeb.52.gmail; Wed, 29 May 2013 22:49:57 -0700 (PDT) X-Received: by 10.52.29.142 with SMTP id k14mr3443531vdh.124.1369892997646; Wed, 29 May 2013 22:49:57 -0700 (PDT) Received: from mail-ve0-x229.google.com (mail-ve0-x229.google.com [2607:f8b0:400c:c01::229]) by mx.google.com with ESMTPS id p8si23776587vdv.44.2013.05.29.22.49.57 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 29 May 2013 22:49:57 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c01::229 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c01::229; Received: by mail-ve0-f169.google.com with SMTP id m1so1314818ves.28 for ; Wed, 29 May 2013 22:49:57 -0700 (PDT) X-Received: by 10.220.112.16 with SMTP id u16mr4147840vcp.40.1369892997520; Wed, 29 May 2013 22:49:57 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.229.199 with SMTP id jj7csp2571vcb; Wed, 29 May 2013 22:49:56 -0700 (PDT) X-Received: by 10.68.189.8 with SMTP id ge8mr6129491pbc.199.1369892996183; Wed, 29 May 2013 22:49:56 -0700 (PDT) Received: from mailout3.samsung.com (mailout3.samsung.com. [203.254.224.33]) by mx.google.com with ESMTP id lm2si28833945pab.238.2013.05.29.22.49.55 for ; Wed, 29 May 2013 22:49:56 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of rajeshwari.s@samsung.com designates 203.254.224.33 as permitted sender) client-ip=203.254.224.33; Received: from epcpsbgr4.samsung.com (u144.gpu120.samsung.co.kr [203.254.230.144]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MNL00AZ8K6ZZFA0@mailout3.samsung.com> for patches@linaro.org; Thu, 30 May 2013 14:49:48 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.123]) by epcpsbgr4.samsung.com (EPCPMTA) with SMTP id 1E.48.29708.B78E6A15; Thu, 30 May 2013 14:49:47 +0900 (KST) X-AuditID: cbfee690-b7f6f6d00000740c-07-51a6e87bbcfb Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 66.AB.21068.B78E6A15; Thu, 30 May 2013 14:49:47 +0900 (KST) Received: from rajeshwari-linux.sisodomain.com ([107.108.215.115]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MNL00392K6TQF10@mmp2.samsung.com>; Thu, 30 May 2013 14:49:47 +0900 (KST) From: Rajeshwari Shinde To: u-boot@lists.denx.de Cc: patches@linaro.org, sjg@chromium.org, mk7.kang@samsung.com, u-boot-review@google.com, jagannadh.teki@gmail.com Subject: [PATCH V2] spi: exynos: Support word transfers Date: Thu, 30 May 2013 11:22:36 +0530 Message-id: <1369893156-3954-1-git-send-email-rajeshwari.s@samsung.com> X-Mailer: git-send-email 1.7.4.4 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrLLMWRmVeSWpSXmKPExsWyRsSkWrf6xbJAgzdLzC12bW1hteg40sJo MeXwFxaLb1u2MVosf72R3eLt3k52BzaP2Q0XWTx2zrrL7rFgU6nHnWt72DzO3tnB6NG3ZRVj AFsUl01Kak5mWWqRvl0CV8ajx9dYCh4ZVrxeZ9vAuFSti5GTQ0LARGJrUwcjhC0mceHeerYu Ri4OIYGljBIvn21ggilad2YiE0RiOqPEr8v/WSGciUwSsw68ZQGpYhMwkth6chrYKBEBCYlf /VfBbGaBEolZp4+B2cIC5hJXDv4Bsjk4WARUJbru8oCEeQXcJd6+2Q51hYLEsalfweZLCDSz S3S+2A2WYBEQkPg2+RALSK+EgKzEpgPMEPWSEgdX3GCZwCi4gJFhFaNoakFyQXFSepGJXnFi bnFpXrpecn7uJkZg0J7+92zCDsZ7B6wPMSYDjZvILCWanA8M+rySeENjMyMLUxNTYyNzSzPS hJXEedVbrAOFBNITS1KzU1MLUovii0pzUosPMTJxcEo1MFpGVH/1cTh+ZN8U9a3/lrj5JGdp 1dwqP9X252xYVNK7x6FbJLbzrD64IFAi4pfzDJ0rk0vERL+WLQlwr7zwWrk8bKfXpX/XlpyR OdS5wG5XyoNFxnscnCY817oz19Vl6TzembvSNlUtav4523ftsbKroW3GGlbL/+Rs6N5l7KO6 WKv4a7yCMKsSS3FGoqEWc1FxIgBVZRmAcAIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrFIsWRmVeSWpSXmKPExsVy+t9jQd3qF8sCDR6/07XYtbWF1aLjSAuj xZTDX1gsvm3Zxmix/PVGdou3ezvZHdg8ZjdcZPHYOesuu8eCTaUed67tYfM4e2cHo0ffllWM AWxRDYw2GamJKalFCql5yfkpmXnptkrewfHO8aZmBoa6hpYW5koKeYm5qbZKLj4Bum6ZOUB3 KCmUJeaUAoUCEouLlfTtME0IDXHTtYBpjND1DQmC6zEyQAMJaxgzHj2+xlLwyLDi9TrbBsal al2MnBwSAiYS685MZIKwxSQu3FvP1sXIxSEkMJ1R4tfl/6wQzkQmiVkH3rKAVLEJGElsPTmN EcQWEZCQ+NV/FcxmFiiRmHX6GJgtLGAuceXgHyCbg4NFQFWi6y4PSJhXwF3i7ZvtjBDLFCSO Tf3KOoGRewEjwypG0dSC5ILipPRcI73ixNzi0rx0veT83E2M4Jh4Jr2DcVWDxSFGAQ5GJR5e Tt1lgUKsiWXFlbmHGCU4mJVEeOfvBQrxpiRWVqUW5ccXleakFh9iTAZaPpFZSjQ5HxiveSXx hsYm5qbGppYmFiZmlqQJK4nzHmy1DhQSSE8sSc1OTS1ILYLZwsTBKdXAWBtdMnW9557iZp8/ 7h8f3z2af5mdOSFkm9wTNbHQ08xis9gWF4k4bmDl33jtzlSfLeWrVpbNs/ty5U8Eh0i+2WID af4X919sUI4XNg+cV/plAsN7edkeXsfyH29cxT+t9txxe8N+m+4pu/s27vldfGrWsgcVDRcv bCw6Eh+8Kv31djEHtuNzriuxFGckGmoxFxUnAgDWCwDLzQIAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-Gm-Message-State: ALoCoQmO7CgaiFIdFGt10fPVWCGaxUIZh3xJkZm3xczM7aU/XK6vfaYkSpKJr+zBBcErKZSHkNL0 X-Original-Sender: rajeshwari.s@samsung.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c01::229 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Since SPI register access is so expensive, it is worth transferring data a word at a time if we can. This complicates the driver unfortunately. Use the byte-swapping feature to avoid having to convert to/from big endian in software. This change increases speed from about 2MB/s to about 4.5MB/s. Based on "[PATCH V2] spi: exynos: Minimise access to SPI FIFO level" Signed-off-by: Simon Glass Signed-off-by: Rajeshwari Shinde --- Changes in V2: - Rebased on [PATCH V2] spi: exynos: Minimise access to SPI FIFO level arch/arm/include/asm/arch-exynos/spi.h | 11 ++++- drivers/spi/exynos_spi.c | 79 ++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h index 7cab1e9..e67ad27 100644 --- a/arch/arm/include/asm/arch-exynos/spi.h +++ b/arch/arm/include/asm/arch-exynos/spi.h @@ -34,7 +34,7 @@ struct exynos_spi { unsigned int rx_data; /* 0x1c */ unsigned int pkt_cnt; /* 0x20 */ unsigned char reserved2[4]; - unsigned char reserved3[4]; + unsigned int swap_cfg; /* 0x28 */ unsigned int fb_clk; /* 0x2c */ unsigned char padding[0xffd0]; }; @@ -74,5 +74,14 @@ struct exynos_spi { /* Packet Count */ #define SPI_PACKET_CNT_EN (1 << 16) +/* Swap config */ +#define SPI_TX_SWAP_EN (1 << 0) +#define SPI_TX_BYTE_SWAP (1 << 2) +#define SPI_TX_HWORD_SWAP (1 << 3) +#define SPI_TX_BYTE_SWAP (1 << 2) +#define SPI_RX_SWAP_EN (1 << 4) +#define SPI_RX_BYTE_SWAP (1 << 6) +#define SPI_RX_HWORD_SWAP (1 << 7) + #endif /* __ASSEMBLY__ */ #endif diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c index bcca3d6..4dda23b 100644 --- a/drivers/spi/exynos_spi.c +++ b/drivers/spi/exynos_spi.c @@ -216,12 +216,29 @@ static void spi_get_fifo_levels(struct exynos_spi *regs, * * @param regs SPI peripheral registers * @param count Number of bytes to transfer + * @param step Number of bytes to transfer in each packet (1 or 4) */ -static void spi_request_bytes(struct exynos_spi *regs, int count) +static void spi_request_bytes(struct exynos_spi *regs, int count, int step) { + /* For word address we need to swap bytes */ + if (step == 4) { + setbits_le32(®s->mode_cfg, + SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD); + count /= 4; + setbits_le32(®s->swap_cfg, SPI_TX_SWAP_EN | SPI_RX_SWAP_EN | + SPI_TX_BYTE_SWAP | SPI_RX_BYTE_SWAP | + SPI_TX_HWORD_SWAP | SPI_RX_HWORD_SWAP); + } else { + /* Select byte access and clear the swap configuration */ + clrbits_le32(®s->mode_cfg, + SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD); + writel(0, ®s->swap_cfg); + } + assert(count && count < (1 << 16)); setbits_le32(®s->ch_cfg, SPI_CH_RST); clrbits_le32(®s->ch_cfg, SPI_CH_RST); + writel(count | SPI_PACKET_CNT_EN, ®s->pkt_cnt); } @@ -236,6 +253,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, int toread; unsigned start = get_timer(0); int stopping; + int step; out_bytes = in_bytes = todo; @@ -243,10 +261,19 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, !(spi_slave->mode & SPI_SLAVE); /* + * Try to transfer words if we can. This helps read performance at + * SPI clock speeds above about 20MHz. + */ + step = 1; + if (!((todo | (uintptr_t)rxp | (uintptr_t)txp) & 3) && + !spi_slave->skip_preamble) + step = 4; + + /* * If there's something to send, do a software reset and set a * transaction size. */ - spi_request_bytes(regs, todo); + spi_request_bytes(regs, todo, step); /* * Bytes are transmitted/received in pairs. Wait to receive all the @@ -259,14 +286,26 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, /* Keep the fifos full/empty. */ spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl); + + /* + * Don't completely fill the txfifo, since we don't want our + * rxfifo to overflow, and it may already contain data. + */ while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) { - temp = txp ? *txp++ : 0xff; + if (!txp) + temp = -1; + else if (step == 4) + temp = *(uint32_t *)txp; + else + temp = *txp; writel(temp, ®s->tx_data); - out_bytes--; - tx_lvl++; + out_bytes -= step; + if (txp) + txp += step; + tx_lvl += step; } - if (rx_lvl > 0) { - while (rx_lvl > 0) { + if (rx_lvl >= step) { + while (rx_lvl >= step) { temp = readl(®s->rx_data); if (spi_slave->skip_preamble) { if (temp == SPI_PREAMBLE_END_BYTE) { @@ -274,12 +313,18 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, stopping = 0; } } else { - if (rxp || stopping) - *rxp++ = temp; - in_bytes--; + if (rxp || stopping) { + if (step == 4) + *(uint32_t *)rxp = temp; + else + *rxp = temp; + rxp += step; + } + in_bytes -= step; } - toread--; - rx_lvl--; + toread -= step; + rx_lvl -= step; + } } else if (!toread) { /* * We have run out of input data, but haven't read @@ -291,7 +336,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, out_bytes = in_bytes; toread = in_bytes; txp = NULL; - spi_request_bytes(regs, toread); + spi_request_bytes(regs, toread, step); } if (spi_slave->skip_preamble && get_timer(start) > 100) { printf("SPI timeout: in_bytes=%d, out_bytes=%d, ", @@ -335,10 +380,14 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, if ((flags & SPI_XFER_BEGIN)) spi_cs_activate(slave); - /* Exynos SPI limits each transfer to 65535 bytes */ + /* + * Exynos SPI limits each transfer to 65535 transfers. To keep + * things simple, allow a maximum of 65532 bytes. We could allow + * more in word mode, but the performance difference is small. + */ bytelen = bitlen / 8; for (upto = 0; !ret && upto < bytelen; upto += todo) { - todo = min(bytelen - upto, (1 << 16) - 1); + todo = min(bytelen - upto, (1 << 16) - 4); ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags); if (ret) break;