aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorAndrea Paterniani <a.paterniani@swapp-eng.it>2007-05-08 03:32:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:15 -0400
commit814a8d50eb1d88cedcef97567be53ee0d4512631 (patch)
treeedf10598ae95e5729edca3095b60641606b62939 /Documentation
parent735ce95e6b9a262d1fbc0ddb5620deb3a29d1067 (diff)
/dev/spidevB.C interface
Add a filesystem API for <linux/spi/spi.h> stack. The initial version of this interface is purely synchronous. dbrownell@users.sourceforge.net: Cleaned up, bugfixed; much simplified; added preliminary documentation. Works with mdev given CONFIG_SYSFS_DEPRECATED; and presumably udev. Updated SPI_IOC_MESSAGE ioctl to full spi_message semantics, supporting groups of one or more transfers (each of which may be full duplex if desired). This is marked as EXPERIMENTAL with an explicit disclaimer that the API (notably the ioctls) is subject to change. Signed-off-by: Andrea Paterniani <a.paterniani@swapp-eng.it> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/spi/spidev307
1 files changed, 307 insertions, 0 deletions
diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev
new file mode 100644
index 000000000000..5c8e1b988a08
--- /dev/null
+++ b/Documentation/spi/spidev
@@ -0,0 +1,307 @@
1SPI devices have a limited userspace API, supporting basic half-duplex
2read() and write() access to SPI slave devices. Using ioctl() requests,
3full duplex transfers and device I/O configuration are also available.
4
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/ioctl.h>
8 #include <linux/types.h>
9 #include <linux/spi/spidev.h>
10
11Some reasons you might want to use this programming interface include:
12
13 * Prototyping in an environment that's not crash-prone; stray pointers
14 in userspace won't normally bring down any Linux system.
15
16 * Developing simple protocols used to talk to microcontrollers acting
17 as SPI slaves, which you may need to change quite often.
18
19Of course there are drivers that can never be written in userspace, because
20they need to access kernel interfaces (such as IRQ handlers or other layers
21of the driver stack) that are not accessible to userspace.
22
23
24DEVICE CREATION, DRIVER BINDING
25===============================
26The simplest way to arrange to use this driver is to just list it in the
27spi_board_info for a device as the driver it should use: the "modalias"
28entry is "spidev", matching the name of the driver exposing this API.
29Set up the other device characteristics (bits per word, SPI clocking,
30chipselect polarity, etc) as usual, so you won't always need to override
31them later.
32
33(Sysfs also supports userspace driven binding/unbinding of drivers to
34devices. That mechanism might be supported here in the future.)
35
36When you do that, the sysfs node for the SPI device will include a child
37device node with a "dev" attribute that will be understood by udev or mdev.
38(Larger systems will have "udev". Smaller ones may configure "mdev" into
39busybox; it's less featureful, but often enough.) For a SPI device with
40chipselect C on bus B, you should see:
41
42 /dev/spidevB.C ... character special device, major number 153 with
43 a dynamically chosen minor device number. This is the node
44 that userspace programs will open, created by "udev" or "mdev".
45
46 /sys/devices/.../spiB.C ... as usual, the SPI device node will
47 be a child of its SPI master controller.
48
49 /sys/class/spidev/spidevB.C ... created when the "spidev" driver
50 binds to that device. (Directory or symlink, based on whether
51 or not you enabled the "deprecated sysfs files" Kconfig option.)
52
53Do not try to manage the /dev character device special file nodes by hand.
54That's error prone, and you'd need to pay careful attention to system
55security issues; udev/mdev should already be configured securely.
56
57If you unbind the "spidev" driver from that device, those two "spidev" nodes
58(in sysfs and in /dev) should automatically be removed (respectively by the
59kernel and by udev/mdev). You can unbind by removing the "spidev" driver
60module, which will affect all devices using this driver. You can also unbind
61by having kernel code remove the SPI device, probably by removing the driver
62for its SPI controller (so its spi_master vanishes).
63
64Since this is a standard Linux device driver -- even though it just happens
65to expose a low level API to userspace -- it can be associated with any number
66of devices at a time. Just provide one spi_board_info record for each such
67SPI device, and you'll get a /dev device node for each device.
68
69
70BASIC CHARACTER DEVICE API
71==========================
72Normal open() and close() operations on /dev/spidevB.D files work as you
73would expect.
74
75Standard read() and write() operations are obviously only half-duplex, and
76the chipselect is deactivated between those operations. Full-duplex access,
77and composite operation without chipselect de-activation, is available using
78the SPI_IOC_MESSAGE(N) request.
79
80Several ioctl() requests let your driver read or override the device's current
81settings for data transfer parameters:
82
83 SPI_IOC_RD_MODE, SPI_IOC_WR_MODE ... pass a pointer to a byte which will
84 return (RD) or assign (WR) the SPI transfer mode. Use the constants
85 SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
86 (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
87 sample on trailing edge iff this is set) flags.
88
89 SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
90 which will return (RD) or assign (WR) the bit justification used to
91 transfer SPI words. Zero indicates MSB-first; other values indicate
92 the less common LSB-first encoding. In both cases the specified value
93 is right-justified in each word, so that unused (TX) or undefined (RX)
94 bits are in the MSBs.
95
96 SPI_IOC_RD_BITS_PER_WORD, SPI_IOC_WR_BITS_PER_WORD ... pass a pointer to
97 a byte which will return (RD) or assign (WR) the number of bits in
98 each SPI transfer word. The value zero signifies eight bits.
99
100 SPI_IOC_RD_MAX_SPEED_HZ, SPI_IOC_WR_MAX_SPEED_HZ ... pass a pointer to a
101 u32 which will return (RD) or assign (WR) the maximum SPI transfer
102 speed, in Hz. The controller can't necessarily assign that specific
103 clock speed.
104
105NOTES:
106
107 - At this time there is no async I/O support; everything is purely
108 synchronous.
109
110 - There's currently no way to report the actual bit rate used to
111 shift data to/from a given device.
112
113 - From userspace, you can't currently change the chip select polarity;
114 that could corrupt transfers to other devices sharing the SPI bus.
115 Each SPI device is deselected when it's not in active use, allowing
116 other drivers to talk to other devices.
117
118 - There's a limit on the number of bytes each I/O request can transfer
119 to the SPI device. It defaults to one page, but that can be changed
120 using a module parameter.
121
122 - Because SPI has no low-level transfer acknowledgement, you usually
123 won't see any I/O errors when talking to a non-existent device.
124
125
126FULL DUPLEX CHARACTER DEVICE API
127================================
128
129See the sample program below for one example showing the use of the full
130duplex programming interface. (Although it doesn't perform a full duplex
131transfer.) The model is the same as that used in the kernel spi_sync()
132request; the individual transfers offer the same capabilities as are
133available to kernel drivers (except that it's not asynchronous).
134
135The example shows one half-duplex RPC-style request and response message.
136These requests commonly require that the chip not be deselected between
137the request and response. Several such requests could be chained into
138a single kernel request, even allowing the chip to be deselected after
139each response. (Other protocol options include changing the word size
140and bitrate for each transfer segment.)
141
142To make a full duplex request, provide both rx_buf and tx_buf for the
143same transfer. It's even OK if those are the same buffer.
144
145
146SAMPLE PROGRAM
147==============
148
149-------------------------------- CUT HERE
150#include <stdio.h>
151#include <unistd.h>
152#include <stdlib.h>
153#include <fcntl.h>
154#include <string.h>
155
156#include <sys/ioctl.h>
157#include <sys/types.h>
158#include <sys/stat.h>
159
160#include <linux/types.h>
161#include <linux/spi/spidev.h>
162
163
164static int verbose;
165
166static void do_read(int fd, int len)
167{
168 unsigned char buf[32], *bp;
169 int status;
170
171 /* read at least 2 bytes, no more than 32 */
172 if (len < 2)
173 len = 2;
174 else if (len > sizeof(buf))
175 len = sizeof(buf);
176 memset(buf, 0, sizeof buf);
177
178 status = read(fd, buf, len);
179 if (status < 0) {
180 perror("read");
181 return;
182 }
183 if (status != len) {
184 fprintf(stderr, "short read\n");
185 return;
186 }
187
188 printf("read(%2d, %2d): %02x %02x,", len, status,
189 buf[0], buf[1]);
190 status -= 2;
191 bp = buf + 2;
192 while (status-- > 0)
193 printf(" %02x", *bp++);
194 printf("\n");
195}
196
197static void do_msg(int fd, int len)
198{
199 struct spi_ioc_transfer xfer[2];
200 unsigned char buf[32], *bp;
201 int status;
202
203 memset(xfer, 0, sizeof xfer);
204 memset(buf, 0, sizeof buf);
205
206 if (len > sizeof buf)
207 len = sizeof buf;
208
209 buf[0] = 0xaa;
210 xfer[0].tx_buf = (__u64) buf;
211 xfer[0].len = 1;
212
213 xfer[1].rx_buf = (__u64) buf;
214 xfer[1].len = len;
215
216 status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
217 if (status < 0) {
218 perror("SPI_IOC_MESSAGE");
219 return;
220 }
221
222 printf("response(%2d, %2d): ", len, status);
223 for (bp = buf; len; len--)
224 printf(" %02x", *bp++);
225 printf("\n");
226}
227
228static void dumpstat(const char *name, int fd)
229{
230 __u8 mode, lsb, bits;
231 __u32 speed;
232
233 if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
234 perror("SPI rd_mode");
235 return;
236 }
237 if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
238 perror("SPI rd_lsb_fist");
239 return;
240 }
241 if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
242 perror("SPI bits_per_word");
243 return;
244 }
245 if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
246 perror("SPI max_speed_hz");
247 return;
248 }
249
250 printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
251 name, mode, bits, lsb ? "(lsb first) " : "", speed);
252}
253
254int main(int argc, char **argv)
255{
256 int c;
257 int readcount = 0;
258 int msglen = 0;
259 int fd;
260 const char *name;
261
262 while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
263 switch (c) {
264 case 'm':
265 msglen = atoi(optarg);
266 if (msglen < 0)
267 goto usage;
268 continue;
269 case 'r':
270 readcount = atoi(optarg);
271 if (readcount < 0)
272 goto usage;
273 continue;
274 case 'v':
275 verbose++;
276 continue;
277 case 'h':
278 case '?':
279usage:
280 fprintf(stderr,
281 "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
282 argv[0]);
283 return 1;
284 }
285 }
286
287 if ((optind + 1) != argc)
288 goto usage;
289 name = argv[optind];
290
291 fd = open(name, O_RDWR);
292 if (fd < 0) {
293 perror("open");
294 return 1;
295 }
296
297 dumpstat(name, fd);
298
299 if (msglen)
300 do_msg(fd, msglen);
301
302 if (readcount)
303 do_read(fd, readcount);
304
305 close(fd);
306 return 0;
307}