Root/target/linux/ar71xx/files/drivers/spi/ar71xx_spi.c

1/*
2 * Atheros AR71xx SPI Controller driver
3 *
4 * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/spinlock.h>
17#include <linux/workqueue.h>
18#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/spi/spi.h>
21#include <linux/spi/spi_bitbang.h>
22#include <linux/bitops.h>
23
24#include <asm/mach-ar71xx/ar71xx.h>
25#include <asm/mach-ar71xx/platform.h>
26
27#define DRV_DESC "Atheros AR71xx SPI Controller driver"
28#define DRV_VERSION "0.2.4"
29#define DRV_NAME "ar71xx-spi"
30
31#undef PER_BIT_READ
32
33struct ar71xx_spi {
34    struct spi_bitbang bitbang;
35    u32 ioc_base;
36    u32 reg_ctrl;
37
38    void __iomem *base;
39
40    struct platform_device *pdev;
41    u32 (*get_ioc_base)(u8 chip_select, int cs_high,
42                        int is_on);
43};
44
45static inline u32 ar71xx_spi_rr(struct ar71xx_spi *sp, unsigned reg)
46{
47    return __raw_readl(sp->base + reg);
48}
49
50static inline void ar71xx_spi_wr(struct ar71xx_spi *sp, unsigned reg, u32 val)
51{
52    __raw_writel(val, sp->base + reg);
53}
54
55static inline struct ar71xx_spi *spidev_to_sp(struct spi_device *spi)
56{
57    return spi_master_get_devdata(spi->master);
58}
59
60static u32 ar71xx_spi_get_ioc_base(u8 chip_select, int cs_high, int is_on)
61{
62    u32 ret;
63
64    if (is_on == AR71XX_SPI_CS_INACTIVE)
65        ret = SPI_IOC_CS_ALL;
66    else
67        ret = SPI_IOC_CS_ALL & ~SPI_IOC_CS(chip_select);
68
69    return ret;
70}
71
72static void ar71xx_spi_chipselect(struct spi_device *spi, int value)
73{
74    struct ar71xx_spi *sp = spidev_to_sp(spi);
75    void __iomem *base = sp->base;
76    u32 ioc_base;
77
78    switch (value) {
79    case BITBANG_CS_INACTIVE:
80        ioc_base = sp->get_ioc_base(spi->chip_select,
81                    (spi->mode & SPI_CS_HIGH) != 0,
82                    AR71XX_SPI_CS_INACTIVE);
83        __raw_writel(ioc_base, base + SPI_REG_IOC);
84        break;
85
86    case BITBANG_CS_ACTIVE:
87        ioc_base = sp->get_ioc_base(spi->chip_select,
88                    (spi->mode & SPI_CS_HIGH) != 0,
89                    AR71XX_SPI_CS_ACTIVE);
90
91        __raw_writel(ioc_base, base + SPI_REG_IOC);
92        sp->ioc_base = ioc_base;
93        break;
94    }
95}
96
97static void ar71xx_spi_setup_regs(struct spi_device *spi)
98{
99    struct ar71xx_spi *sp = spidev_to_sp(spi);
100
101    /* enable GPIO mode */
102    ar71xx_spi_wr(sp, SPI_REG_FS, SPI_FS_GPIO);
103
104    /* save CTRL register */
105    sp->reg_ctrl = ar71xx_spi_rr(sp, SPI_REG_CTRL);
106
107    /* TODO: setup speed? */
108    ar71xx_spi_wr(sp, SPI_REG_CTRL, 0x43);
109}
110
111static void ar71xx_spi_restore_regs(struct spi_device *spi)
112{
113    struct ar71xx_spi *sp = spidev_to_sp(spi);
114
115    /* restore CTRL register */
116    ar71xx_spi_wr(sp, SPI_REG_CTRL, sp->reg_ctrl);
117    /* disable GPIO mode */
118    ar71xx_spi_wr(sp, SPI_REG_FS, 0);
119}
120
121static int ar71xx_spi_setup(struct spi_device *spi)
122{
123    int status;
124
125    if (spi->bits_per_word > 32)
126        return -EINVAL;
127
128    if (!spi->controller_state)
129        ar71xx_spi_setup_regs(spi);
130
131    status = spi_bitbang_setup(spi);
132    if (status && !spi->controller_state)
133        ar71xx_spi_restore_regs(spi);
134
135    return status;
136}
137
138static void ar71xx_spi_cleanup(struct spi_device *spi)
139{
140    ar71xx_spi_restore_regs(spi);
141    spi_bitbang_cleanup(spi);
142}
143
144static u32 ar71xx_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
145                    u32 word, u8 bits)
146{
147    struct ar71xx_spi *sp = spidev_to_sp(spi);
148    void __iomem *base = sp->base;
149    u32 ioc = sp->ioc_base;
150    u32 ret;
151
152    /* clock starts at inactive polarity */
153    for (word <<= (32 - bits); likely(bits); bits--) {
154        u32 out;
155
156        if (word & (1 << 31))
157            out = ioc | SPI_IOC_DO;
158        else
159            out = ioc & ~SPI_IOC_DO;
160
161        /* setup MSB (to slave) on trailing edge */
162        __raw_writel(out, base + SPI_REG_IOC);
163
164        __raw_writel(out | SPI_IOC_CLK, base + SPI_REG_IOC);
165
166        word <<= 1;
167
168#ifdef PER_BIT_READ
169        /* sample MSB (from slave) on leading edge */
170        ret = __raw_readl(base + SPI_REG_RDS);
171        __raw_writel(out, base + SPI_REG_IOC);
172#endif
173
174    }
175
176#ifndef PER_BIT_READ
177    ret = __raw_readl(base + SPI_REG_RDS);
178#endif
179    return ret;
180}
181
182static int ar71xx_spi_probe(struct platform_device *pdev)
183{
184    struct spi_master *master;
185    struct ar71xx_spi *sp;
186    struct ar71xx_spi_platform_data *pdata;
187    struct resource *r;
188    int ret;
189
190    master = spi_alloc_master(&pdev->dev, sizeof(*sp));
191    if (master == NULL) {
192        dev_err(&pdev->dev, "failed to allocate spi master\n");
193        return -ENOMEM;
194    }
195
196    sp = spi_master_get_devdata(master);
197    platform_set_drvdata(pdev, sp);
198
199    pdata = pdev->dev.platform_data;
200
201    master->setup = ar71xx_spi_setup;
202    master->cleanup = ar71xx_spi_cleanup;
203
204    sp->bitbang.master = spi_master_get(master);
205    sp->bitbang.chipselect = ar71xx_spi_chipselect;
206    sp->bitbang.txrx_word[SPI_MODE_0] = ar71xx_spi_txrx_mode0;
207    sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
208
209    sp->get_ioc_base = ar71xx_spi_get_ioc_base;
210    if (pdata) {
211        sp->bitbang.master->bus_num = pdata->bus_num;
212        sp->bitbang.master->num_chipselect = pdata->num_chipselect;
213        if (pdata->get_ioc_base)
214            sp->get_ioc_base = pdata->get_ioc_base;
215    } else {
216        sp->bitbang.master->bus_num = 0;
217        sp->bitbang.master->num_chipselect = 3;
218    }
219
220    r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
221    if (r == NULL) {
222        ret = -ENOENT;
223        goto err1;
224    }
225
226    sp->base = ioremap_nocache(r->start, r->end - r->start + 1);
227    if (!sp->base) {
228        ret = -ENXIO;
229        goto err1;
230    }
231
232    ret = spi_bitbang_start(&sp->bitbang);
233    if (!ret)
234        return 0;
235
236    iounmap(sp->base);
237err1:
238    platform_set_drvdata(pdev, NULL);
239    spi_master_put(sp->bitbang.master);
240
241    return ret;
242}
243
244static int ar71xx_spi_remove(struct platform_device *pdev)
245{
246    struct ar71xx_spi *sp = platform_get_drvdata(pdev);
247
248    spi_bitbang_stop(&sp->bitbang);
249    iounmap(sp->base);
250    platform_set_drvdata(pdev, NULL);
251    spi_master_put(sp->bitbang.master);
252
253    return 0;
254}
255
256static struct platform_driver ar71xx_spi_drv = {
257    .probe = ar71xx_spi_probe,
258    .remove = ar71xx_spi_remove,
259    .driver = {
260        .name = DRV_NAME,
261        .owner = THIS_MODULE,
262    },
263};
264
265static int __init ar71xx_spi_init(void)
266{
267    printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
268    return platform_driver_register(&ar71xx_spi_drv);
269}
270module_init(ar71xx_spi_init);
271
272static void __exit ar71xx_spi_exit(void)
273{
274    platform_driver_unregister(&ar71xx_spi_drv);
275}
276module_exit(ar71xx_spi_exit);
277
278MODULE_ALIAS("platform:" DRV_NAME);
279MODULE_DESCRIPTION(DRV_DESC);
280MODULE_VERSION(DRV_VERSION);
281MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
282MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>");
283MODULE_LICENSE("GPL v2");
284

Archive Download this file



interactive