aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi_bitbang_txrx.h93
-rw-r--r--drivers/spi/spi_butterfly.c3
-rw-r--r--drivers/spi/spi_gpio.c3
-rw-r--r--drivers/spi/spi_lm70llp.c3
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c3
-rw-r--r--drivers/spi/spi_sh_sci.c3
-rw-r--r--include/linux/spi/spi_bitbang.h101
7 files changed, 98 insertions, 111 deletions
diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi_bitbang_txrx.h
new file mode 100644
index 000000000000..fc033bbf9180
--- /dev/null
+++ b/drivers/spi/spi_bitbang_txrx.h
@@ -0,0 +1,93 @@
1/*
2 * Mix this utility code with some glue code to get one of several types of
3 * simple SPI master driver. Two do polled word-at-a-time I/O:
4 *
5 * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
6 * expanding the per-word routines from the inline templates below.
7 *
8 * - Drivers for controllers resembling bare shift registers. Provide
9 * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
10 * that use your controller's clock and chipselect registers.
11 *
12 * Some hardware works well with requests at spi_transfer scope:
13 *
14 * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
15 * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
16 * and custom setup()/cleanup() methods.
17 */
18
19/*
20 * The code that knows what GPIO pins do what should have declared four
21 * functions, ideally as inlines, before including this header:
22 *
23 * void setsck(struct spi_device *, int is_on);
24 * void setmosi(struct spi_device *, int is_on);
25 * int getmiso(struct spi_device *);
26 * void spidelay(unsigned);
27 *
28 * setsck()'s is_on parameter is a zero/nonzero boolean.
29 *
30 * setmosi()'s is_on parameter is a zero/nonzero boolean.
31 *
32 * getmiso() is required to return 0 or 1 only. Any other value is invalid
33 * and will result in improper operation.
34 *
35 * A non-inlined routine would call bitbang_txrx_*() routines. The
36 * main loop could easily compile down to a handful of instructions,
37 * especially if the delay is a NOP (to run at peak speed).
38 *
39 * Since this is software, the timings may not be exactly what your board's
40 * chips need ... there may be several reasons you'd need to tweak timings
41 * in these routines, not just make to make it faster or slower to match a
42 * particular CPU clock rate.
43 */
44
45static inline u32
46bitbang_txrx_be_cpha0(struct spi_device *spi,
47 unsigned nsecs, unsigned cpol,
48 u32 word, u8 bits)
49{
50 /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
51
52 /* clock starts at inactive polarity */
53 for (word <<= (32 - bits); likely(bits); bits--) {
54
55 /* setup MSB (to slave) on trailing edge */
56 setmosi(spi, word & (1 << 31));
57 spidelay(nsecs); /* T(setup) */
58
59 setsck(spi, !cpol);
60 spidelay(nsecs);
61
62 /* sample MSB (from slave) on leading edge */
63 word <<= 1;
64 word |= getmiso(spi);
65 setsck(spi, cpol);
66 }
67 return word;
68}
69
70static inline u32
71bitbang_txrx_be_cpha1(struct spi_device *spi,
72 unsigned nsecs, unsigned cpol,
73 u32 word, u8 bits)
74{
75 /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
76
77 /* clock starts at inactive polarity */
78 for (word <<= (32 - bits); likely(bits); bits--) {
79
80 /* setup MSB (to slave) on leading edge */
81 setsck(spi, !cpol);
82 setmosi(spi, word & (1 << 31));
83 spidelay(nsecs); /* T(setup) */
84
85 setsck(spi, cpol);
86 spidelay(nsecs);
87
88 /* sample MSB (from slave) on trailing edge */
89 word <<= 1;
90 word |= getmiso(spi);
91 }
92 return word;
93}
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index c2184866fa9c..8b5281281111 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -149,8 +149,7 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
149#define spidelay(X) do{}while(0) 149#define spidelay(X) do{}while(0)
150//#define spidelay ndelay 150//#define spidelay ndelay
151 151
152#define EXPAND_BITBANG_TXRX 152#include "spi_bitbang_txrx.h"
153#include <linux/spi/spi_bitbang.h>
154 153
155static u32 154static u32
156butterfly_txrx_word_mode0(struct spi_device *spi, 155butterfly_txrx_word_mode0(struct spi_device *spi,
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
index 26bd03e61855..7edbd5807e0e 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi_gpio.c
@@ -127,8 +127,7 @@ static inline int getmiso(const struct spi_device *spi)
127 */ 127 */
128#define spidelay(nsecs) do {} while (0) 128#define spidelay(nsecs) do {} while (0)
129 129
130#define EXPAND_BITBANG_TXRX 130#include "spi_bitbang_txrx.h"
131#include <linux/spi/spi_bitbang.h>
132 131
133/* 132/*
134 * These functions can leverage inline expansion of GPIO calls to shrink 133 * These functions can leverage inline expansion of GPIO calls to shrink
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
index 568c781ad91c..86fb7b5993db 100644
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi_lm70llp.c
@@ -174,8 +174,7 @@ static inline int getmiso(struct spi_device *s)
174} 174}
175/*--------------------------------------------------------------------*/ 175/*--------------------------------------------------------------------*/
176 176
177#define EXPAND_BITBANG_TXRX 1 177#include "spi_bitbang_txrx.h"
178#include <linux/spi/spi_bitbang.h>
179 178
180static void lm70_chipselect(struct spi_device *spi, int value) 179static void lm70_chipselect(struct spi_device *spi, int value)
181{ 180{
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index bbf9371cd284..8979a75dbd7b 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -58,8 +58,7 @@ static inline u32 getmiso(struct spi_device *dev)
58 58
59#define spidelay(x) ndelay(x) 59#define spidelay(x) ndelay(x)
60 60
61#define EXPAND_BITBANG_TXRX 61#include "spi_bitbang_txrx.h"
62#include <linux/spi/spi_bitbang.h>
63 62
64 63
65static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, 64static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c
index a65c12ffa733..a511be7961a0 100644
--- a/drivers/spi/spi_sh_sci.c
+++ b/drivers/spi/spi_sh_sci.c
@@ -78,8 +78,7 @@ static inline u32 getmiso(struct spi_device *dev)
78 78
79#define spidelay(x) ndelay(x) 79#define spidelay(x) ndelay(x)
80 80
81#define EXPAND_BITBANG_TXRX 81#include "spi_bitbang_txrx.h"
82#include <linux/spi/spi_bitbang.h>
83 82
84static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, 83static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
85 unsigned nsecs, u32 word, u8 bits) 84 unsigned nsecs, u32 word, u8 bits)
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 3274c507b8a9..f987a2bee16a 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -1,24 +1,6 @@
1#ifndef __SPI_BITBANG_H 1#ifndef __SPI_BITBANG_H
2#define __SPI_BITBANG_H 2#define __SPI_BITBANG_H
3 3
4/*
5 * Mix this utility code with some glue code to get one of several types of
6 * simple SPI master driver. Two do polled word-at-a-time I/O:
7 *
8 * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
9 * expanding the per-word routines from the inline templates below.
10 *
11 * - Drivers for controllers resembling bare shift registers. Provide
12 * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
13 * that use your controller's clock and chipselect registers.
14 *
15 * Some hardware works well with requests at spi_transfer scope:
16 *
17 * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
18 * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
19 * and custom setup()/cleanup() methods.
20 */
21
22#include <linux/workqueue.h> 4#include <linux/workqueue.h>
23 5
24struct spi_bitbang { 6struct spi_bitbang {
@@ -68,86 +50,3 @@ extern int spi_bitbang_start(struct spi_bitbang *spi);
68extern int spi_bitbang_stop(struct spi_bitbang *spi); 50extern int spi_bitbang_stop(struct spi_bitbang *spi);
69 51
70#endif /* __SPI_BITBANG_H */ 52#endif /* __SPI_BITBANG_H */
71
72/*-------------------------------------------------------------------------*/
73
74#ifdef EXPAND_BITBANG_TXRX
75
76/*
77 * The code that knows what GPIO pins do what should have declared four
78 * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX
79 * and including this header:
80 *
81 * void setsck(struct spi_device *, int is_on);
82 * void setmosi(struct spi_device *, int is_on);
83 * int getmiso(struct spi_device *);
84 * void spidelay(unsigned);
85 *
86 * setsck()'s is_on parameter is a zero/nonzero boolean.
87 *
88 * setmosi()'s is_on parameter is a zero/nonzero boolean.
89 *
90 * getmiso() is required to return 0 or 1 only. Any other value is invalid
91 * and will result in improper operation.
92 *
93 * A non-inlined routine would call bitbang_txrx_*() routines. The
94 * main loop could easily compile down to a handful of instructions,
95 * especially if the delay is a NOP (to run at peak speed).
96 *
97 * Since this is software, the timings may not be exactly what your board's
98 * chips need ... there may be several reasons you'd need to tweak timings
99 * in these routines, not just make to make it faster or slower to match a
100 * particular CPU clock rate.
101 */
102
103static inline u32
104bitbang_txrx_be_cpha0(struct spi_device *spi,
105 unsigned nsecs, unsigned cpol,
106 u32 word, u8 bits)
107{
108 /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
109
110 /* clock starts at inactive polarity */
111 for (word <<= (32 - bits); likely(bits); bits--) {
112
113 /* setup MSB (to slave) on trailing edge */
114 setmosi(spi, word & (1 << 31));
115 spidelay(nsecs); /* T(setup) */
116
117 setsck(spi, !cpol);
118 spidelay(nsecs);
119
120 /* sample MSB (from slave) on leading edge */
121 word <<= 1;
122 word |= getmiso(spi);
123 setsck(spi, cpol);
124 }
125 return word;
126}
127
128static inline u32
129bitbang_txrx_be_cpha1(struct spi_device *spi,
130 unsigned nsecs, unsigned cpol,
131 u32 word, u8 bits)
132{
133 /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
134
135 /* clock starts at inactive polarity */
136 for (word <<= (32 - bits); likely(bits); bits--) {
137
138 /* setup MSB (to slave) on leading edge */
139 setsck(spi, !cpol);
140 setmosi(spi, word & (1 << 31));
141 spidelay(nsecs); /* T(setup) */
142
143 setsck(spi, cpol);
144 spidelay(nsecs);
145
146 /* sample MSB (from slave) on trailing edge */
147 word <<= 1;
148 word |= getmiso(spi);
149 }
150 return word;
151}
152
153#endif /* EXPAND_BITBANG_TXRX */