diff options
-rw-r--r-- | drivers/spi/spi-ath79.c | 44 |
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 | |||
33 | struct ath79_spi { | 38 | struct 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 | ||
40 | static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) | 47 | static 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 | ||
62 | static 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 | |||
55 | static void ath79_spi_chipselect(struct spi_device *spi, int is_active) | 68 | static 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 | ||
281 | err_clk_disable: | ||
282 | clk_disable(sp->clk); | ||
283 | err_clk_put: | ||
284 | clk_put(sp->clk); | ||
245 | err_unmap: | 285 | err_unmap: |
246 | iounmap(sp->base); | 286 | iounmap(sp->base); |
247 | err_put_master: | 287 | err_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); |