aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-12-27 04:42:24 -0500
committerGrant Likely <grant.likely@secretlab.ca>2013-02-05 07:57:02 -0500
commit440114fdb13cbc53ea734bcc05b86bcf5b1e430c (patch)
tree142bd5e2a53569a200011624d7bf2a8863eab3dd
parentba486a2a29b629413f89e0490edb02a8ccc3bb8f (diff)
spi/ath79: add delay between SCK changes
The driver uses the "as fast as it can" approach to drive the SCK signal. However this does not work with certain low speed SPI chips (e.g. the PCF2123 RTC chip). The patch adds per-bit slowdowns in order to be able to use the driver with such chips as well. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r--drivers/spi/spi-ath79.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 9a5d7791c5fb..e02528244451 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -24,17 +24,24 @@
24#include <linux/spi/spi_bitbang.h> 24#include <linux/spi/spi_bitbang.h>
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/gpio.h> 26#include <linux/gpio.h>
27#include <linux/clk.h>
28#include <linux/err.h>
27 29
28#include <asm/mach-ath79/ar71xx_regs.h> 30#include <asm/mach-ath79/ar71xx_regs.h>
29#include <asm/mach-ath79/ath79_spi_platform.h> 31#include <asm/mach-ath79/ath79_spi_platform.h>
30 32
31#define DRV_NAME "ath79-spi" 33#define DRV_NAME "ath79-spi"
32 34
35#define ATH79_SPI_RRW_DELAY_FACTOR 12000
36#define MHZ (1000 * 1000)
37
33struct ath79_spi { 38struct ath79_spi {
34 struct spi_bitbang bitbang; 39 struct spi_bitbang bitbang;
35 u32 ioc_base; 40 u32 ioc_base;
36 u32 reg_ctrl; 41 u32 reg_ctrl;
37 void __iomem *base; 42 void __iomem *base;
43 struct clk *clk;
44 unsigned rrw_delay;
38}; 45};
39 46
40static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) 47static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
52 return spi_master_get_devdata(spi->master); 59 return spi_master_get_devdata(spi->master);
53} 60}
54 61
62static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
63{
64 if (nsecs > sp->rrw_delay)
65 ndelay(nsecs - sp->rrw_delay);
66}
67
55static void ath79_spi_chipselect(struct spi_device *spi, int is_active) 68static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
56{ 69{
57 struct ath79_spi *sp = ath79_spidev_to_sp(spi); 70 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
@@ -184,7 +197,9 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
184 197
185 /* setup MSB (to slave) on trailing edge */ 198 /* setup MSB (to slave) on trailing edge */
186 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); 199 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
200 ath79_spi_delay(sp, nsecs);
187 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK); 201 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
202 ath79_spi_delay(sp, nsecs);
188 203
189 word <<= 1; 204 word <<= 1;
190 } 205 }
@@ -198,6 +213,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
198 struct ath79_spi *sp; 213 struct ath79_spi *sp;
199 struct ath79_spi_platform_data *pdata; 214 struct ath79_spi_platform_data *pdata;
200 struct resource *r; 215 struct resource *r;
216 unsigned long rate;
201 int ret; 217 int ret;
202 218
203 master = spi_alloc_master(&pdev->dev, sizeof(*sp)); 219 master = spi_alloc_master(&pdev->dev, sizeof(*sp));
@@ -236,12 +252,36 @@ static int ath79_spi_probe(struct platform_device *pdev)
236 goto err_put_master; 252 goto err_put_master;
237 } 253 }
238 254
255 sp->clk = clk_get(&pdev->dev, "ahb");
256 if (IS_ERR(sp->clk)) {
257 ret = PTR_ERR(sp->clk);
258 goto err_unmap;
259 }
260
261 ret = clk_enable(sp->clk);
262 if (ret)
263 goto err_clk_put;
264
265 rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
266 if (!rate) {
267 ret = -EINVAL;
268 goto err_clk_disable;
269 }
270
271 sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
272 dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
273 sp->rrw_delay);
274
239 ret = spi_bitbang_start(&sp->bitbang); 275 ret = spi_bitbang_start(&sp->bitbang);
240 if (ret) 276 if (ret)
241 goto err_unmap; 277 goto err_clk_disable;
242 278
243 return 0; 279 return 0;
244 280
281err_clk_disable:
282 clk_disable(sp->clk);
283err_clk_put:
284 clk_put(sp->clk);
245err_unmap: 285err_unmap:
246 iounmap(sp->base); 286 iounmap(sp->base);
247err_put_master: 287err_put_master:
@@ -256,6 +296,8 @@ static int ath79_spi_remove(struct platform_device *pdev)
256 struct ath79_spi *sp = platform_get_drvdata(pdev); 296 struct ath79_spi *sp = platform_get_drvdata(pdev);
257 297
258 spi_bitbang_stop(&sp->bitbang); 298 spi_bitbang_stop(&sp->bitbang);
299 clk_disable(sp->clk);
300 clk_put(sp->clk);
259 iounmap(sp->base); 301 iounmap(sp->base);
260 platform_set_drvdata(pdev, NULL); 302 platform_set_drvdata(pdev, NULL);
261 spi_master_put(sp->bitbang.master); 303 spi_master_put(sp->bitbang.master);