Skip to content

Commit

Permalink
ar71xx: improve SPI flash read/write performance
Browse files Browse the repository at this point in the history
mtd_speedtest results:

                        page write speed
                    old         new       delta
DB120            209 KiB/s   226 KiB/s     +8.13%
TL-WR1043ND v1   122 KiB/s   148 KiB/s    +21.31%
TL-WR703N v1     153 KiB/s   194 KiB/s    +26.80%
TL-MR3220 v1     130 KiB/s   156 KiB/s    +20.00%
TL-WR2543ND v1   158 KiB/s   202 KiB/s    +27.85%
TL-WR741ND v2    122 KiB/s   152 KiB/s    +24.59%
ALFA AP96        229 KiB/s   260 KiB/s    +13.54%
WNDR3700         202 KiB/s   223 KiB/s    +10.40%

                         page read speed
                    old        new       delta
DB120            691 KiB/s   929 KiB/s    +34.44%
TL-WR1043ND v1   372 KiB/s   754 KiB/s   +102.69%
TL-WR703N v1     375 KiB/s   745 KiB/s    +98.67%
TL-MR3220 v1     372 KiB/s   752 KiB/s   +102.15%
TL-WR2543ND v1   307 KiB/s   564 KiB/s    +83.71%
TL-WR741ND v2    315 KiB/s   525 KiB/s    +66.67%
ALFA AP96        515 KiB/s   702 KiB/s    +36.31%
WNDR3700         515 KiB/s   697 KiB/s    +35.34%

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31117 3c298f89-4303-0410-b956-a3cf2f4a3e73
  • Loading branch information
juhosg committed Mar 27, 2012
1 parent ad01160 commit ac19ad9
Show file tree
Hide file tree
Showing 18 changed files with 514 additions and 324 deletions.
@@ -1,4 +1,4 @@
From 48b7e765e6e097d20d809fadd17a4355d26ad6d5 Mon Sep 17 00:00:00 2001
From 8e948c035dd7983eccc3a889f2497e64044f3a31 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 11 Jan 2012 20:06:35 +0100
Subject: [PATCH 1/7] spi/ath79: add delay between SCK changes
Expand All @@ -12,31 +12,111 @@ well.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/spi/spi-ath79.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
drivers/spi/spi-ath79.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 43 insertions(+), 1 deletions(-)

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -52,6 +52,12 @@ static inline struct ath79_spi *ath79_sp
@@ -24,17 +24,24 @@
#include <linux/spi/spi_bitbang.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>

#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79_spi_platform.h>

#define DRV_NAME "ath79-spi"

+#define ATH79_SPI_RRW_DELAY_FACTOR 12000
+#define MHZ (1000 * 1000)
+
struct ath79_spi {
struct spi_bitbang bitbang;
u32 ioc_base;
u32 reg_ctrl;
void __iomem *base;
+ struct clk *clk;
+ unsigned rrw_delay;
};

static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_sp
return spi_master_get_devdata(spi->master);
}

+static inline void ath79_spi_delay(unsigned nsecs)
+static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
+{
+ if (nsecs)
+ ndelay(nsecs);
+ if (nsecs > sp->rrw_delay)
+ ndelay(nsecs - sp->rrw_delay);
+}
+
static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
@@ -184,7 +190,9 @@ static u32 ath79_spi_txrx_mode0(struct s
@@ -184,7 +197,9 @@ static u32 ath79_spi_txrx_mode0(struct s

/* setup MSB (to slave) on trailing edge */
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+ ath79_spi_delay(nsecs);
+ ath79_spi_delay(sp, nsecs);
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+ ath79_spi_delay(nsecs);
+ ath79_spi_delay(sp, nsecs);

word <<= 1;
}
@@ -198,6 +213,7 @@ static __devinit int ath79_spi_probe(str
struct ath79_spi *sp;
struct ath79_spi_platform_data *pdata;
struct resource *r;
+ unsigned long rate;
int ret;

master = spi_alloc_master(&pdev->dev, sizeof(*sp));
@@ -239,12 +255,36 @@ static __devinit int ath79_spi_probe(str
goto err_put_master;
}

+ sp->clk = clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(sp->clk)) {
+ ret = PTR_ERR(sp->clk);
+ goto err_unmap;
+ }
+
+ ret = clk_enable(sp->clk);
+ if (ret)
+ goto err_clk_put;
+
+ rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
+ if (!rate) {
+ ret = -EINVAL;
+ goto err_clk_disable;
+ }
+
+ sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
+ dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
+ sp->rrw_delay);
+
ret = spi_bitbang_start(&sp->bitbang);
if (ret)
- goto err_unmap;
+ goto err_clk_disable;

return 0;

+err_clk_disable:
+ clk_disable(sp->clk);
+err_clk_put:
+ clk_put(sp->clk);
err_unmap:
iounmap(sp->base);
err_put_master:
@@ -259,6 +299,8 @@ static __devexit int ath79_spi_remove(st
struct ath79_spi *sp = platform_get_drvdata(pdev);

spi_bitbang_stop(&sp->bitbang);
+ clk_disable(sp->clk);
+ clk_put(sp->clk);
iounmap(sp->base);
platform_set_drvdata(pdev, NULL);
spi_master_put(sp->bitbang.master);
@@ -1,20 +1,21 @@
From 0ad8cbbb978bc01de08eadd3357ea188302b83ce Mon Sep 17 00:00:00 2001
From ea7e40aedae58b7a0f0ccd8658063de499734874 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 11 Jan 2012 20:33:41 +0100
Subject: [PATCH 2/7] spi/ath79: add missing HIGH->LOW SCK transition

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/spi/spi-ath79.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
drivers/spi/spi-ath79.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -193,6 +193,7 @@ static u32 ath79_spi_txrx_mode0(struct s
ath79_spi_delay(nsecs);
@@ -200,6 +200,8 @@ static u32 ath79_spi_txrx_mode0(struct s
ath79_spi_delay(sp, nsecs);
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
ath79_spi_delay(nsecs);
+ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
ath79_spi_delay(sp, nsecs);
+ if (bits == 1)
+ ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);

word <<= 1;
}
@@ -1,4 +1,4 @@
From 7385ff2cb72d6a0107890760466b9564aa5204c1 Mon Sep 17 00:00:00 2001
From ecf57a64feb737dec1da72aab21dccd30a88ba19 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 9 Jan 2012 15:03:28 +0100
Subject: [PATCH 3/7] spi/ath79: remove superfluous chip select code
Expand All @@ -15,7 +15,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -121,12 +121,6 @@ static int ath79_spi_setup_cs(struct spi
@@ -128,12 +128,6 @@ static int ath79_spi_setup_cs(struct spi
gpio_free(cdata->gpio);
return status;
}
Expand Down
@@ -1,4 +1,4 @@
From c5bfb0c760a5d8de7ffc3a6acfb8c782be6af1a5 Mon Sep 17 00:00:00 2001
From dd5b424b0b3f0370f9b63594ad53c16989b6ad78 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 9 Jan 2012 15:04:21 +0100
Subject: [PATCH 4/7] spi/ath79: use gpio_request_one
Expand All @@ -12,15 +12,15 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -93,6 +93,7 @@ static int ath79_spi_setup_cs(struct spi
@@ -100,6 +100,7 @@ static int ath79_spi_setup_cs(struct spi
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
struct ath79_spi_controller_data *cdata;
+ int status;

cdata = spi->controller_data;
if (spi->chip_select && !cdata)
@@ -108,22 +109,21 @@ static int ath79_spi_setup_cs(struct spi
@@ -115,22 +116,21 @@ static int ath79_spi_setup_cs(struct spi
/* TODO: setup speed? */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);

Expand Down
@@ -1,15 +1,26 @@
From 4518ae06e5fc953abfd9c2b66c6155fc2b2696ce Mon Sep 17 00:00:00 2001
From 25e681989198e94656eab9df22b8b761abd2ae26 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Mon, 9 Jan 2012 15:00:46 +0100
Subject: [PATCH 5/7] spi/ath79: introduce ath79_spi_{en,dis}able helpers
Subject: [PATCH 5/7] spi/ath79: avoid multiple initialization of the SPI controller

Currently we are initializing the SPI controller in
the chip select line function, and that function is
called once for each SPI device on the bus. If a
board has multiple SPI devices, the controller will
be initialized multiple times.

Introduce ath79_spi_{en,dis}able helper functions,
and call those from probe/response in order to avoid
the mutliple initialization of the controller.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/spi/spi-ath79.c | 41 +++++++++++++++++++++++++----------------
1 files changed, 25 insertions(+), 16 deletions(-)
drivers/spi/spi-ath79.c | 41 ++++++++++++++++++++++++-----------------
1 files changed, 24 insertions(+), 17 deletions(-)

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -89,16 +89,8 @@ static void ath79_spi_chipselect(struct
@@ -96,16 +96,8 @@ static void ath79_spi_chipselect(struct

}

Expand All @@ -27,7 +38,7 @@ Subject: [PATCH 5/7] spi/ath79: introduce ath79_spi_{en,dis}able helpers
/* enable GPIO mode */
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);

@@ -108,6 +100,24 @@ static int ath79_spi_setup_cs(struct spi
@@ -115,6 +107,24 @@ static int ath79_spi_setup_cs(struct spi

/* TODO: setup speed? */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
Expand All @@ -52,7 +63,7 @@ Subject: [PATCH 5/7] spi/ath79: introduce ath79_spi_{en,dis}able helpers

status = 0;
if (spi->chip_select) {
@@ -128,17 +138,10 @@ static int ath79_spi_setup_cs(struct spi
@@ -135,17 +145,10 @@ static int ath79_spi_setup_cs(struct spi

static void ath79_spi_cleanup_cs(struct spi_device *spi)
{
Expand All @@ -70,29 +81,28 @@ Subject: [PATCH 5/7] spi/ath79: introduce ath79_spi_{en,dis}able helpers
}

static int ath79_spi_setup(struct spi_device *spi)
@@ -242,13 +245,15 @@ static __devinit int ath79_spi_probe(str
goto err_put_master;
}
@@ -271,12 +274,15 @@ static __devinit int ath79_spi_probe(str
dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
sp->rrw_delay);

+ ath79_spi_enable(sp);
ret = spi_bitbang_start(&sp->bitbang);
if (ret)
- goto err_unmap;
- goto err_clk_disable;
+ goto err_disable;

return 0;

-err_unmap:
+err_disable:
+ ath79_spi_disable(sp);
iounmap(sp->base);
err_put_master:
platform_set_drvdata(pdev, NULL);
@@ -262,6 +267,7 @@ static __devexit int ath79_spi_remove(st
err_clk_disable:
clk_disable(sp->clk);
err_clk_put:
@@ -295,6 +301,7 @@ static __devexit int ath79_spi_remove(st
struct ath79_spi *sp = platform_get_drvdata(pdev);

spi_bitbang_stop(&sp->bitbang);
+ ath79_spi_disable(sp);
clk_disable(sp->clk);
clk_put(sp->clk);
iounmap(sp->base);
platform_set_drvdata(pdev, NULL);
spi_master_put(sp->bitbang.master);
@@ -1,4 +1,4 @@
From 1025bfbe327b3f9f7227e781c71751d5251803cb Mon Sep 17 00:00:00 2001
From e01dcc2835017b55e936bd150ddab29bfcf2c63c Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 11 Jan 2012 22:19:32 +0100
Subject: [PATCH 6/7] spi/ath79: add shutdown handler
Expand All @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -262,7 +262,7 @@ err_put_master:
@@ -296,7 +296,7 @@ err_put_master:
return ret;
}

Expand All @@ -19,7 +19,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
{
struct ath79_spi *sp = platform_get_drvdata(pdev);

@@ -271,13 +271,23 @@ static __devexit int ath79_spi_remove(st
@@ -307,13 +307,23 @@ static __devexit int ath79_spi_remove(st
iounmap(sp->base);
platform_set_drvdata(pdev, NULL);
spi_master_put(sp->bitbang.master);
Expand Down

0 comments on commit ac19ad9

Please sign in to comment.