Root/target/linux/ar71xx/patches-3.6/200-spi-ath79-add-delay-between-SCK-changes.patch

1From cbb3ade4765bc715b5c2eae4a7b6eaf3ff7ad958 Mon Sep 17 00:00:00 2001
2From: Gabor Juhos <juhosg@openwrt.org>
3Date: Wed, 11 Jan 2012 20:06:35 +0100
4Subject: [PATCH 28/34] spi/ath79: add delay between SCK changes
5
6The driver uses the "as fast as it can" approach
7to drive the SCK signal. However this does not
8work with certain low speed SPI chips (e.g. the
9PCF2123 RTC chip). Add per-bit slowdowns in order
10to be able to use the driver with such chips as
11well.
12
13Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
14---
15 drivers/spi/spi-ath79.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
16 1 files changed, 43 insertions(+), 1 deletions(-)
17
18--- a/drivers/spi/spi-ath79.c
19+++ b/drivers/spi/spi-ath79.c
20@@ -24,17 +24,24 @@
21 #include <linux/spi/spi_bitbang.h>
22 #include <linux/bitops.h>
23 #include <linux/gpio.h>
24+#include <linux/clk.h>
25+#include <linux/err.h>
26 
27 #include <asm/mach-ath79/ar71xx_regs.h>
28 #include <asm/mach-ath79/ath79_spi_platform.h>
29 
30 #define DRV_NAME "ath79-spi"
31 
32+#define ATH79_SPI_RRW_DELAY_FACTOR 12000
33+#define MHZ (1000 * 1000)
34+
35 struct ath79_spi {
36     struct spi_bitbang bitbang;
37     u32 ioc_base;
38     u32 reg_ctrl;
39     void __iomem *base;
40+ struct clk *clk;
41+ unsigned rrw_delay;
42 };
43 
44 static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
45@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_sp
46     return spi_master_get_devdata(spi->master);
47 }
48 
49+static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
50+{
51+ if (nsecs > sp->rrw_delay)
52+ ndelay(nsecs - sp->rrw_delay);
53+}
54+
55 static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
56 {
57     struct ath79_spi *sp = ath79_spidev_to_sp(spi);
58@@ -184,7 +197,9 @@ static u32 ath79_spi_txrx_mode0(struct s
59 
60         /* setup MSB (to slave) on trailing edge */
61         ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
62+ ath79_spi_delay(sp, nsecs);
63         ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
64+ ath79_spi_delay(sp, nsecs);
65 
66         word <<= 1;
67     }
68@@ -198,6 +213,7 @@ static __devinit int ath79_spi_probe(str
69     struct ath79_spi *sp;
70     struct ath79_spi_platform_data *pdata;
71     struct resource *r;
72+ unsigned long rate;
73     int ret;
74 
75     master = spi_alloc_master(&pdev->dev, sizeof(*sp));
76@@ -236,12 +252,36 @@ static __devinit int ath79_spi_probe(str
77         goto err_put_master;
78     }
79 
80+ sp->clk = clk_get(&pdev->dev, "ahb");
81+ if (IS_ERR(sp->clk)) {
82+ ret = PTR_ERR(sp->clk);
83+ goto err_unmap;
84+ }
85+
86+ ret = clk_enable(sp->clk);
87+ if (ret)
88+ goto err_clk_put;
89+
90+ rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
91+ if (!rate) {
92+ ret = -EINVAL;
93+ goto err_clk_disable;
94+ }
95+
96+ sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
97+ dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
98+ sp->rrw_delay);
99+
100     ret = spi_bitbang_start(&sp->bitbang);
101     if (ret)
102- goto err_unmap;
103+ goto err_clk_disable;
104 
105     return 0;
106 
107+err_clk_disable:
108+ clk_disable(sp->clk);
109+err_clk_put:
110+ clk_put(sp->clk);
111 err_unmap:
112     iounmap(sp->base);
113 err_put_master:
114@@ -256,6 +296,8 @@ static __devexit int ath79_spi_remove(st
115     struct ath79_spi *sp = platform_get_drvdata(pdev);
116 
117     spi_bitbang_stop(&sp->bitbang);
118+ clk_disable(sp->clk);
119+ clk_put(sp->clk);
120     iounmap(sp->base);
121     platform_set_drvdata(pdev, NULL);
122     spi_master_put(sp->bitbang.master);
123

Archive Download this file



interactive