aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/Kconfig18
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi_gpio.c360
-rw-r--r--include/linux/spi/spi_gpio.h60
4 files changed, 438 insertions, 1 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b9d0efb6803f..4a6fe01831a8 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -78,7 +78,7 @@ config SPI_AU1550
78 will be called au1550_spi. 78 will be called au1550_spi.
79 79
80config SPI_BITBANG 80config SPI_BITBANG
81 tristate "Bitbanging SPI master" 81 tristate "Utilities for Bitbanging SPI masters"
82 help 82 help
83 With a few GPIO pins, your system can bitbang the SPI protocol. 83 With a few GPIO pins, your system can bitbang the SPI protocol.
84 Select this to get SPI support through I/O pins (GPIO, parallel 84 Select this to get SPI support through I/O pins (GPIO, parallel
@@ -100,6 +100,22 @@ config SPI_BUTTERFLY
100 inexpensive battery powered microcontroller evaluation board. 100 inexpensive battery powered microcontroller evaluation board.
101 This same cable can be used to flash new firmware. 101 This same cable can be used to flash new firmware.
102 102
103config SPI_GPIO
104 tristate "GPIO-based bitbanging SPI Master"
105 depends on GENERIC_GPIO
106 select SPI_BITBANG
107 help
108 This simple GPIO bitbanging SPI master uses the arch-neutral GPIO
109 interface to manage MOSI, MISO, SCK, and chipselect signals. SPI
110 slaves connected to a bus using this driver are configured as usual,
111 except that the spi_board_info.controller_data holds the GPIO number
112 for the chipselect used by this controller driver.
113
114 Note that this driver often won't achieve even 1 Mbit/sec speeds,
115 making it unusually slow for SPI. If your platform can inline
116 GPIO operations, you should be able to leverage that for better
117 speed with a custom version of this driver; see the source code.
118
103config SPI_IMX 119config SPI_IMX
104 tristate "Freescale iMX SPI controller" 120 tristate "Freescale iMX SPI controller"
105 depends on ARCH_IMX && EXPERIMENTAL 121 depends on ARCH_IMX && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ccf18de34e1e..5e9f521b8844 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
16obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o 16obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
17obj-$(CONFIG_SPI_AU1550) += au1550_spi.o 17obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
18obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o 18obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
19obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
19obj-$(CONFIG_SPI_IMX) += spi_imx.o 20obj-$(CONFIG_SPI_IMX) += spi_imx.o
20obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o 21obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
21obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o 22obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
new file mode 100644
index 000000000000..49698cabc30d
--- /dev/null
+++ b/drivers/spi/spi_gpio.c
@@ -0,0 +1,360 @@
1/*
2 * spi_gpio.c - SPI master driver using generic bitbanged GPIO
3 *
4 * Copyright (C) 2006,2008 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/platform_device.h>
23#include <linux/gpio.h>
24
25#include <linux/spi/spi.h>
26#include <linux/spi/spi_bitbang.h>
27#include <linux/spi/spi_gpio.h>
28
29
30/*
31 * This bitbanging SPI master driver should help make systems usable
32 * when a native hardware SPI engine is not available, perhaps because
33 * its driver isn't yet working or because the I/O pins it requires
34 * are used for other purposes.
35 *
36 * platform_device->driver_data ... points to spi_gpio
37 *
38 * spi->controller_state ... reserved for bitbang framework code
39 * spi->controller_data ... holds chipselect GPIO
40 *
41 * spi->master->dev.driver_data ... points to spi_gpio->bitbang
42 */
43
44struct spi_gpio {
45 struct spi_bitbang bitbang;
46 struct spi_gpio_platform_data pdata;
47 struct platform_device *pdev;
48};
49
50/*----------------------------------------------------------------------*/
51
52/*
53 * Because the overhead of going through four GPIO procedure calls
54 * per transferred bit can make performance a problem, this code
55 * is set up so that you can use it in either of two ways:
56 *
57 * - The slow generic way: set up platform_data to hold the GPIO
58 * numbers used for MISO/MOSI/SCK, and issue procedure calls for
59 * each of them. This driver can handle several such busses.
60 *
61 * - The quicker inlined way: only helps with platform GPIO code
62 * that inlines operations for constant GPIOs. This can give
63 * you tight (fast!) inner loops, but each such bus needs a
64 * new driver. You'll define a new C file, with Makefile and
65 * Kconfig support; the C code can be a total of six lines:
66 *
67 * #define DRIVER_NAME "myboard_spi2"
68 * #define SPI_MISO_GPIO 119
69 * #define SPI_MOSI_GPIO 120
70 * #define SPI_SCK_GPIO 121
71 * #define SPI_N_CHIPSEL 4
72 * #include "spi_gpio.c"
73 */
74
75#ifndef DRIVER_NAME
76#define DRIVER_NAME "spi_gpio"
77
78#define GENERIC_BITBANG /* vs tight inlines */
79
80/* all functions referencing these symbols must define pdata */
81#define SPI_MISO_GPIO ((pdata)->miso)
82#define SPI_MOSI_GPIO ((pdata)->mosi)
83#define SPI_SCK_GPIO ((pdata)->sck)
84
85#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
86
87#endif
88
89/*----------------------------------------------------------------------*/
90
91static inline const struct spi_gpio_platform_data * __pure
92spi_to_pdata(const struct spi_device *spi)
93{
94 const struct spi_bitbang *bang;
95 const struct spi_gpio *spi_gpio;
96
97 bang = spi_master_get_devdata(spi->master);
98 spi_gpio = container_of(bang, struct spi_gpio, bitbang);
99 return &spi_gpio->pdata;
100}
101
102/* this is #defined to avoid unused-variable warnings when inlining */
103#define pdata spi_to_pdata(spi)
104
105static inline void setsck(const struct spi_device *spi, int is_on)
106{
107 gpio_set_value(SPI_SCK_GPIO, is_on);
108}
109
110static inline void setmosi(const struct spi_device *spi, int is_on)
111{
112 gpio_set_value(SPI_MOSI_GPIO, is_on);
113}
114
115static inline int getmiso(const struct spi_device *spi)
116{
117 return gpio_get_value(SPI_MISO_GPIO);
118}
119
120#undef pdata
121
122/*
123 * NOTE: this clocks "as fast as we can". It "should" be a function of the
124 * requested device clock. Software overhead means we usually have trouble
125 * reaching even one Mbit/sec (except when we can inline bitops), so for now
126 * we'll just assume we never need additional per-bit slowdowns.
127 */
128#define spidelay(nsecs) do {} while (0)
129
130#define EXPAND_BITBANG_TXRX
131#include <linux/spi/spi_bitbang.h>
132
133/*
134 * These functions can leverage inline expansion of GPIO calls to shrink
135 * costs for a txrx bit, often by factors of around ten (by instruction
136 * count). That is particularly visible for larger word sizes, but helps
137 * even with default 8-bit words.
138 *
139 * REVISIT overheads calling these functions for each word also have
140 * significant performance costs. Having txrx_bufs() calls that inline
141 * the txrx_word() logic would help performance, e.g. on larger blocks
142 * used with flash storage or MMC/SD. There should also be ways to make
143 * GCC be less stupid about reloading registers inside the I/O loops,
144 * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
145 */
146
147static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
148 unsigned nsecs, u32 word, u8 bits)
149{
150 return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
151}
152
153static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
154 unsigned nsecs, u32 word, u8 bits)
155{
156 return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
157}
158
159static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
160 unsigned nsecs, u32 word, u8 bits)
161{
162 return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
163}
164
165static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
166 unsigned nsecs, u32 word, u8 bits)
167{
168 return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
169}
170
171/*----------------------------------------------------------------------*/
172
173static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
174{
175 unsigned long cs = (unsigned long) spi->controller_data;
176
177 /* set initial clock polarity */
178 if (is_active)
179 setsck(spi, spi->mode & SPI_CPOL);
180
181 /* SPI is normally active-low */
182 gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
183}
184
185static int spi_gpio_setup(struct spi_device *spi)
186{
187 unsigned long cs = (unsigned long) spi->controller_data;
188 int status = 0;
189
190 if (spi->bits_per_word > 32)
191 return -EINVAL;
192
193 if (!spi->controller_state) {
194 status = gpio_request(cs, spi->dev.bus_id);
195 if (status)
196 return status;
197 status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
198 }
199 if (!status)
200 status = spi_bitbang_setup(spi);
201 if (status) {
202 if (!spi->controller_state)
203 gpio_free(cs);
204 }
205 return status;
206}
207
208static void spi_gpio_cleanup(struct spi_device *spi)
209{
210 unsigned long cs = (unsigned long) spi->controller_data;
211
212 gpio_free(cs);
213 spi_bitbang_cleanup(spi);
214}
215
216static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
217{
218 int value;
219
220 value = gpio_request(pin, label);
221 if (value == 0) {
222 if (is_in)
223 value = gpio_direction_input(pin);
224 else
225 value = gpio_direction_output(pin, 0);
226 }
227 return value;
228}
229
230static int __init
231spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
232{
233 int value;
234
235 /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
236
237 value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
238 if (value)
239 goto done;
240
241 value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
242 if (value)
243 goto free_mosi;
244
245 value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
246 if (value)
247 goto free_miso;
248
249 goto done;
250
251free_miso:
252 gpio_free(SPI_MISO_GPIO);
253free_mosi:
254 gpio_free(SPI_MOSI_GPIO);
255done:
256 return value;
257}
258
259static int __init spi_gpio_probe(struct platform_device *pdev)
260{
261 int status;
262 struct spi_master *master;
263 struct spi_gpio *spi_gpio;
264 struct spi_gpio_platform_data *pdata;
265
266 pdata = pdev->dev.platform_data;
267#ifdef GENERIC_BITBANG
268 if (!pdata || !pdata->num_chipselect)
269 return -ENODEV;
270#endif
271
272 status = spi_gpio_request(pdata, dev_name(&pdev->dev));
273 if (status < 0)
274 return status;
275
276 master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
277 if (!master) {
278 status = -ENOMEM;
279 goto gpio_free;
280 }
281 spi_gpio = spi_master_get_devdata(master);
282 platform_set_drvdata(pdev, spi_gpio);
283
284 spi_gpio->pdev = pdev;
285 if (pdata)
286 spi_gpio->pdata = *pdata;
287
288 master->bus_num = pdev->id;
289 master->num_chipselect = SPI_N_CHIPSEL;
290 master->setup = spi_gpio_setup;
291 master->cleanup = spi_gpio_cleanup;
292
293 spi_gpio->bitbang.master = spi_master_get(master);
294 spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
295 spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
296 spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
297 spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
298 spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
299 spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
300 spi_gpio->bitbang.flags = SPI_CS_HIGH;
301
302 status = spi_bitbang_start(&spi_gpio->bitbang);
303 if (status < 0) {
304 spi_master_put(spi_gpio->bitbang.master);
305gpio_free:
306 gpio_free(SPI_MISO_GPIO);
307 gpio_free(SPI_MOSI_GPIO);
308 gpio_free(SPI_SCK_GPIO);
309 spi_master_put(master);
310 }
311
312 return status;
313}
314
315static int __exit spi_gpio_remove(struct platform_device *pdev)
316{
317 struct spi_gpio *spi_gpio;
318 struct spi_gpio_platform_data *pdata;
319 int status;
320
321 spi_gpio = platform_get_drvdata(pdev);
322 pdata = pdev->dev.platform_data;
323
324 /* stop() unregisters child devices too */
325 status = spi_bitbang_stop(&spi_gpio->bitbang);
326 spi_master_put(spi_gpio->bitbang.master);
327
328 platform_set_drvdata(pdev, NULL);
329
330 gpio_free(SPI_MISO_GPIO);
331 gpio_free(SPI_MOSI_GPIO);
332 gpio_free(SPI_SCK_GPIO);
333
334 return status;
335}
336
337MODULE_ALIAS("platform:" DRIVER_NAME);
338
339static struct platform_driver spi_gpio_driver = {
340 .driver.name = DRIVER_NAME,
341 .driver.owner = THIS_MODULE,
342 .remove = __exit_p(spi_gpio_remove),
343};
344
345static int __init spi_gpio_init(void)
346{
347 return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
348}
349module_init(spi_gpio_init);
350
351static void __exit spi_gpio_exit(void)
352{
353 platform_driver_unregister(&spi_gpio_driver);
354}
355module_exit(spi_gpio_exit);
356
357
358MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
359MODULE_AUTHOR("David Brownell");
360MODULE_LICENSE("GPL");
diff --git a/include/linux/spi/spi_gpio.h b/include/linux/spi/spi_gpio.h
new file mode 100644
index 000000000000..0f01a0f1f40c
--- /dev/null
+++ b/include/linux/spi/spi_gpio.h
@@ -0,0 +1,60 @@
1#ifndef __LINUX_SPI_GPIO_H
2#define __LINUX_SPI_GPIO_H
3
4/*
5 * For each bitbanged SPI bus, set up a platform_device node with:
6 * - name "spi_gpio"
7 * - id the same as the SPI bus number it implements
8 * - dev.platform data pointing to a struct spi_gpio_platform_data
9 *
10 * Or, see the driver code for information about speedups that are
11 * possible on platforms that support inlined access for GPIOs (no
12 * spi_gpio_platform_data is used).
13 *
14 * Use spi_board_info with these busses in the usual way, being sure
15 * that the controller_data being the GPIO used for each device's
16 * chipselect:
17 *
18 * static struct spi_board_info ... [] = {
19 * ...
20 * // this slave uses GPIO 42 for its chipselect
21 * .controller_data = (void *) 42,
22 * ...
23 * // this one uses GPIO 86 for its chipselect
24 * .controller_data = (void *) 86,
25 * ...
26 * };
27 *
28 * If the bitbanged bus is later switched to a "native" controller,
29 * that platform_device and controller_data should be removed.
30 */
31
32/**
33 * struct spi_gpio_platform_data - parameter for bitbanged SPI master
34 * @sck: number of the GPIO used for clock output
35 * @mosi: number of the GPIO used for Master Output, Slave In (MOSI) data
36 * @miso: number of the GPIO used for Master Input, Slave Output (MISO) data
37 * @num_chipselect: how many slaves to allow
38 *
39 * All GPIO signals used with the SPI bus managed through this driver
40 * (chipselects, MOSI, MISO, SCK) must be configured as GPIOs, instead
41 * of some alternate function.
42 *
43 * It can be convenient to use this driver with pins that have alternate
44 * functions associated with a "native" SPI controller if a driver for that
45 * controller is not available, or is missing important functionality.
46 *
47 * On platforms which can do so, configure MISO with a weak pullup unless
48 * there's an external pullup on that signal. That saves power by avoiding
49 * floating signals. (A weak pulldown would save power too, but many
50 * drivers expect to see all-ones data as the no slave "response".)
51 */
52struct spi_gpio_platform_data {
53 unsigned sck;
54 unsigned mosi;
55 unsigned miso;
56
57 u16 num_chipselect;
58};
59
60#endif /* __LINUX_SPI_GPIO_H */