From patchwork Mon Mar 25 07:56:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajeshwari Shinde X-Patchwork-Id: 15574 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 256B823E10 for ; Mon, 25 Mar 2013 07:50:43 +0000 (UTC) Received: from mail-vb0-f50.google.com (mail-vb0-f50.google.com [209.85.212.50]) by fiordland.canonical.com (Postfix) with ESMTP id 4EF43A19256 for ; Mon, 25 Mar 2013 07:50:42 +0000 (UTC) Received: by mail-vb0-f50.google.com with SMTP id ft2so3775614vbb.37 for ; Mon, 25 Mar 2013 00:50:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf: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; bh=Os6YoAvwfMb2rjFyHd7r4hVx4X97BPSmkgYX+Bf2It8=; b=k0gwCea+jx08a5aXa9hNiqQzVq2Hmrof7u79la7d0OoUu/AfUsj2f0cgolVSR3n8/5 rC4K7DAZF21J/OGCM4lUtFFPH7vHwLN4J3wkXM1WuEinsu54hj7WjvW+72FNjcVhIw8F aQOfWD5q87WJzAbbmkGfquT2iyXGa1+Em5VkWHbkYYdEDXykf6pNEaJE7A/ShOSqb16O VngTc9jmBbj/9TKkaI24kfQB80Ija+7Pe6aAZtFAstxeYJgBy8+cBDmSHc3N+Y/a0mTm 3zZtMI7SRdjByq/UsBnGw29wquQsUtjawvvu6R2XIUblndO7Eb5FbCtjISPOukn9W2AB UxZg== X-Received: by 10.58.253.33 with SMTP id zx1mr493894vec.35.1364197841691; Mon, 25 Mar 2013 00:50:41 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.59.4.204 with SMTP id cg12csp31460ved; Mon, 25 Mar 2013 00:50:40 -0700 (PDT) X-Received: by 10.68.231.70 with SMTP id te6mr15817550pbc.159.1364197839704; Mon, 25 Mar 2013 00:50:39 -0700 (PDT) Received: from mailout4.samsung.com (mailout4.samsung.com. [203.254.224.34]) by mx.google.com with ESMTP id lp7si12882469pab.140.2013.03.25.00.50.38; Mon, 25 Mar 2013 00:50:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of rajeshwari.s@samsung.com designates 203.254.224.34 as permitted sender) client-ip=203.254.224.34; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of rajeshwari.s@samsung.com designates 203.254.224.34 as permitted sender) smtp.mail=rajeshwari.s@samsung.com Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MK70054QHS5UYX0@mailout4.samsung.com>; Mon, 25 Mar 2013 16:50:38 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.123]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id B6.8E.20872.DC100515; Mon, 25 Mar 2013 16:50:38 +0900 (KST) X-AuditID: cbfee68d-b7f786d000005188-ce-515001cd7ae6 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id FF.A2.13494.DC100515; Mon, 25 Mar 2013 16:50:37 +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 <0MK700HTZHS8P280@mmp2.samsung.com>; Mon, 25 Mar 2013 16:50:37 +0900 (KST) From: Rajeshwari Shinde To: u-boot@lists.denx.de Cc: patches@linaro.org, sjg@chromium.org, mk7.kang@samsung.com, chander.kashyap@linaro.org Subject: [PATCH] EXYNOS: SPI: Support word transfers Date: Mon, 25 Mar 2013 13:26:41 +0530 Message-id: <1364198201-10458-1-git-send-email-rajeshwari.s@samsung.com> X-Mailer: git-send-email 1.7.4.4 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrILMWRmVeSWpSXmKPExsWyRsSkWvccY0CgwcSvrBYP199kseg40sJo MeXwFxaLb1u2MVq83dvJ7sDqMbvhIovHnWt72DzO3tnB6NG3ZRVjAEsUl01Kak5mWWqRvl0C V8bs9l/sBWsMKx73nmVqYOxS62Lk5JAQMJFY/rqfHcIWk7hwbz1bFyMXh5DAUkaJl3uXMsEU bdlyjAkiMZ1R4sqr/1BVE5kkZtz6BNbOJmAksfXkNEYQW0RAQuJX/1Uwm1kgRuL1/h9sILYw 0KTeVdtZQWwWAVWJ7v83wXp5BTwkvi+7yQyxTUHi2NSvrCALJARes0nM7jnOBtEgIPFt8iGW LkYOoISsxKYDUPWSEgdX3GCZwCi4gJFhFaNoakFyQXFSepGhXnFibnFpXrpecn7uJkZgcJ7+ 96x3B+PtA9aHGJOBxk1klhJNzgcGd15JvKGxmZGFqYmpsZG5pRlpwkrivGot1oFCAumJJanZ qakFqUXxRaU5qcWHGJk4OKUaGB8YHTIuu1TIVjhZbsfTvzwZ6osbPvyJrLzMsid9/mHha1Iy CyfemCvU8+DOK4VmTQnjToW//f/8OJeulXd4I3P7s2GlidWPC8vDfjwr2rtje+WaVbGJW+7Y M53d33Qmr2/1F++vP22EnQq9W1NZvhprO16O4F8jof536bTQtPyb/WErNQ78SFFiKc5INNRi LipOBABvw2tzZAIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrHIsWRmVeSWpSXmKPExsVy+t9jQd2zjAGBBm9mWVo8XH+TxaLjSAuj xZTDX1gsvm3Zxmjxdm8nuwOrx+yGiywed67tYfM4e2cHo0ffllWMASxRDYw2GamJKalFCql5 yfkpmXnptkrewfHO8aZmBoa6hpYW5koKeYm5qbZKLj4Bum6ZOUCblRTKEnNKgUIBicXFSvp2 mCaEhrjpWsA0Ruj6hgTB9RgZoIGENYwZs9t/sResMax43HuWqYGxS62LkZNDQsBEYsuWY0wQ tpjEhXvr2boYuTiEBKYzSlx59R/KmcgkMePWJ3aQKjYBI4mtJ6cxgtgiAhISv/qvgtnMAjES r/f/YAOxhYGm9q7azgpiswioSnT/vwnWyyvgIfF92U1miG0KEsemfmWdwMi9gJFhFaNoakFy QXFSeq6RXnFibnFpXrpecn7uJkZw6D+T3sG4qsHiEKMAB6MSD69AjX+gEGtiWXFl7iFGCQ5m JRHe6HtAId6UxMqq1KL8+KLSnNTiQ4zJQNsnMkuJJucD4zKvJN7Q2MTc1NjU0sTCxMySNGEl cd6DrdaBQgLpiSWp2ampBalFMFuYODilGhj1uOR+zde50y2zZZlGYfGy/wY6rXMu7OaNCBJN tmj2/fOk//b/AwHZ12ZeWf8qW2Ozz9wfLo/Yf0y4bnNr0ZcnLluVFN0n/TFQ1z63wUJu9+4+ I83CEMPddv/rFnpG3ev0vvu3iv3t+5DHr6vrune2PdBvmMiR4rZ89dNT3hntx8W37tv5cFea EktxRqKhFnNRcSIAUShkd8ECAAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-Gm-Message-State: ALoCoQkzkUx4Y2gONf/Q9Btz08uSo499N9QB6of0hEKhbhrnlwCK9E4kOKAfC6FwFr2qh4q8OJAr 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 "EXYNOS: SPI: Minimise access to SPI FIFO level" link: http://patchwork.ozlabs.org/patch/230034/ Signed-off-by: Simon Glass Signed-off-by: Rajeshwari Shinde Acked-by: Simon Glass Tested-by: Simon Glass --- arch/arm/include/asm/arch-exynos/spi.h | 11 ++++- drivers/spi/exynos_spi.c | 77 +++++++++++++++++++++++++------ 2 files changed, 72 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 7bbf9ce..d1918cf 100644 --- a/drivers/spi/exynos_spi.c +++ b/drivers/spi/exynos_spi.c @@ -218,12 +218,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); } @@ -238,6 +255,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, int toread, preamable_count = 0; unsigned start = get_timer(0); int stopping; + int step; out_bytes = in_bytes = todo; @@ -245,10 +263,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 @@ -260,28 +287,44 @@ 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 && in_bytes) { - while (rx_lvl > 0 && in_bytes) { + if (rx_lvl >= step && in_bytes) { + while (rx_lvl >= step && in_bytes) { temp = readl(®s->rx_data); if (!rxp && !stopping) { - in_bytes--; + in_bytes -= step; } else if (spi_slave->skip_preamble) { if (temp == SPI_PREAMBLE_END_BYTE) { spi_slave->skip_preamble = 0; stopping = 0; } } else { - *rxp++ = temp; - in_bytes--; + if (step == 4) + *(uint32_t *)rxp = temp; + else + *rxp = temp; + in_bytes -= step; + rxp += step; } - toread--; - rx_lvl--; + toread -= step; + rx_lvl -= step; } /* * We have run out of input data, but haven't read enough @@ -293,7 +336,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo, assert(!out_bytes); toread = out_bytes = 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, ", @@ -336,10 +379,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); }