spi.c revision 1.2.4.2 1 1.2.4.2 ad /* $NetBSD: spi.c,v 1.2.4.2 2006/11/18 21:34:49 ad Exp $ */
2 1.2.4.2 ad
3 1.2.4.2 ad /*-
4 1.2.4.2 ad * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
5 1.2.4.2 ad * Copyright (c) 2006 Garrett D'Amore.
6 1.2.4.2 ad * All rights reserved.
7 1.2.4.2 ad *
8 1.2.4.2 ad * Portions of this code were written by Garrett D'Amore for the
9 1.2.4.2 ad * Champaign-Urbana Community Wireless Network Project.
10 1.2.4.2 ad *
11 1.2.4.2 ad * Redistribution and use in source and binary forms, with or
12 1.2.4.2 ad * without modification, are permitted provided that the following
13 1.2.4.2 ad * conditions are met:
14 1.2.4.2 ad * 1. Redistributions of source code must retain the above copyright
15 1.2.4.2 ad * notice, this list of conditions and the following disclaimer.
16 1.2.4.2 ad * 2. Redistributions in binary form must reproduce the above
17 1.2.4.2 ad * copyright notice, this list of conditions and the following
18 1.2.4.2 ad * disclaimer in the documentation and/or other materials provided
19 1.2.4.2 ad * with the distribution.
20 1.2.4.2 ad * 3. All advertising materials mentioning features or use of this
21 1.2.4.2 ad * software must display the following acknowledgements:
22 1.2.4.2 ad * This product includes software developed by the Urbana-Champaign
23 1.2.4.2 ad * Independent Media Center.
24 1.2.4.2 ad * This product includes software developed by Garrett D'Amore.
25 1.2.4.2 ad * 4. Urbana-Champaign Independent Media Center's name and Garrett
26 1.2.4.2 ad * D'Amore's name may not be used to endorse or promote products
27 1.2.4.2 ad * derived from this software without specific prior written permission.
28 1.2.4.2 ad *
29 1.2.4.2 ad * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
30 1.2.4.2 ad * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR
31 1.2.4.2 ad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 1.2.4.2 ad * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 1.2.4.2 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT
34 1.2.4.2 ad * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
35 1.2.4.2 ad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 1.2.4.2 ad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 1.2.4.2 ad * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 1.2.4.2 ad * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 1.2.4.2 ad * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 1.2.4.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 1.2.4.2 ad * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 1.2.4.2 ad */
43 1.2.4.2 ad
44 1.2.4.2 ad #include <sys/cdefs.h>
45 1.2.4.2 ad __KERNEL_RCSID(0, "$NetBSD: spi.c,v 1.2.4.2 2006/11/18 21:34:49 ad Exp $");
46 1.2.4.2 ad
47 1.2.4.2 ad #include "locators.h"
48 1.2.4.2 ad
49 1.2.4.2 ad #include <sys/param.h>
50 1.2.4.2 ad #include <sys/systm.h>
51 1.2.4.2 ad #include <sys/device.h>
52 1.2.4.2 ad #include <sys/malloc.h>
53 1.2.4.2 ad #include <sys/proc.h>
54 1.2.4.2 ad #include <sys/errno.h>
55 1.2.4.2 ad
56 1.2.4.2 ad #include <dev/spi/spivar.h>
57 1.2.4.2 ad
58 1.2.4.2 ad struct spi_softc {
59 1.2.4.2 ad struct device sc_dev;
60 1.2.4.2 ad struct spi_controller sc_controller;
61 1.2.4.2 ad int sc_mode;
62 1.2.4.2 ad int sc_speed;
63 1.2.4.2 ad int sc_nslaves;
64 1.2.4.2 ad struct spi_handle *sc_slaves;
65 1.2.4.2 ad };
66 1.2.4.2 ad
67 1.2.4.2 ad /*
68 1.2.4.2 ad * SPI slave device. We have one of these per slave.
69 1.2.4.2 ad */
70 1.2.4.2 ad struct spi_handle {
71 1.2.4.2 ad struct spi_softc *sh_sc;
72 1.2.4.2 ad struct spi_controller *sh_controller;
73 1.2.4.2 ad int sh_slave;
74 1.2.4.2 ad };
75 1.2.4.2 ad
76 1.2.4.2 ad /*
77 1.2.4.2 ad * API for bus drivers.
78 1.2.4.2 ad */
79 1.2.4.2 ad
80 1.2.4.2 ad int
81 1.2.4.2 ad spibus_print(void *aux, const char *pnp)
82 1.2.4.2 ad {
83 1.2.4.2 ad
84 1.2.4.2 ad if (pnp != NULL)
85 1.2.4.2 ad aprint_normal("spi at %s", pnp);
86 1.2.4.2 ad
87 1.2.4.2 ad return (UNCONF);
88 1.2.4.2 ad }
89 1.2.4.2 ad
90 1.2.4.2 ad
91 1.2.4.2 ad static int
92 1.2.4.2 ad spi_match(struct device *parent, struct cfdata *cf, void *aux)
93 1.2.4.2 ad {
94 1.2.4.2 ad
95 1.2.4.2 ad return 1;
96 1.2.4.2 ad }
97 1.2.4.2 ad
98 1.2.4.2 ad static int
99 1.2.4.2 ad spi_print(void *aux, const char *pnp)
100 1.2.4.2 ad {
101 1.2.4.2 ad struct spi_attach_args *sa = aux;
102 1.2.4.2 ad
103 1.2.4.2 ad if (sa->sa_handle->sh_slave != -1)
104 1.2.4.2 ad aprint_normal(" slave %d", sa->sa_handle->sh_slave);
105 1.2.4.2 ad
106 1.2.4.2 ad return (UNCONF);
107 1.2.4.2 ad }
108 1.2.4.2 ad
109 1.2.4.2 ad static int
110 1.2.4.2 ad spi_search(struct device *parent, struct cfdata *cf, const int *ldesc,
111 1.2.4.2 ad void *aux)
112 1.2.4.2 ad {
113 1.2.4.2 ad struct spi_softc *sc = (void *)parent;
114 1.2.4.2 ad struct spi_attach_args sa;
115 1.2.4.2 ad int addr;
116 1.2.4.2 ad
117 1.2.4.2 ad addr = cf->cf_loc[SPICF_SLAVE];
118 1.2.4.2 ad if ((addr < 0) || (addr >= sc->sc_controller.sct_nslaves)) {
119 1.2.4.2 ad return -1;
120 1.2.4.2 ad }
121 1.2.4.2 ad
122 1.2.4.2 ad sa.sa_handle = &sc->sc_slaves[addr];
123 1.2.4.2 ad
124 1.2.4.2 ad if (config_match(parent, cf, &sa) > 0)
125 1.2.4.2 ad config_attach(parent, cf, &sa, spi_print);
126 1.2.4.2 ad
127 1.2.4.2 ad return 0;
128 1.2.4.2 ad }
129 1.2.4.2 ad
130 1.2.4.2 ad /*
131 1.2.4.2 ad * API for device drivers.
132 1.2.4.2 ad *
133 1.2.4.2 ad * We provide wrapper routines to decouple the ABI for the SPI
134 1.2.4.2 ad * device drivers from the ABI for the SPI bus drivers.
135 1.2.4.2 ad */
136 1.2.4.2 ad static void
137 1.2.4.2 ad spi_attach(struct device *parent, struct device *self, void *aux)
138 1.2.4.2 ad {
139 1.2.4.2 ad struct spi_softc *sc = device_private(self);
140 1.2.4.2 ad struct spibus_attach_args *sba = aux;
141 1.2.4.2 ad int i;
142 1.2.4.2 ad
143 1.2.4.2 ad aprint_naive(": SPI bus\n");
144 1.2.4.2 ad aprint_normal(": SPI bus\n");
145 1.2.4.2 ad
146 1.2.4.2 ad sc->sc_controller = *sba->sba_controller;
147 1.2.4.2 ad /* allocate slave structures */
148 1.2.4.2 ad sc->sc_slaves = malloc(sizeof (struct spi_handle) * sc->sc_nslaves,
149 1.2.4.2 ad M_DEVBUF, M_WAITOK | M_ZERO);
150 1.2.4.2 ad
151 1.2.4.2 ad sc->sc_speed = 0;
152 1.2.4.2 ad sc->sc_mode = -1;
153 1.2.4.2 ad
154 1.2.4.2 ad /*
155 1.2.4.2 ad * Initialize slave handles
156 1.2.4.2 ad */
157 1.2.4.2 ad sc->sc_nslaves = sba->sba_controller->sct_nslaves;
158 1.2.4.2 ad for (i = 0; i < sc->sc_nslaves; i++) {
159 1.2.4.2 ad sc->sc_slaves[i].sh_slave = i;
160 1.2.4.2 ad sc->sc_slaves[i].sh_sc = sc;
161 1.2.4.2 ad sc->sc_slaves[i].sh_controller = &sc->sc_controller;
162 1.2.4.2 ad }
163 1.2.4.2 ad
164 1.2.4.2 ad /*
165 1.2.4.2 ad * Locate and attach child devices
166 1.2.4.2 ad */
167 1.2.4.2 ad config_search_ia(spi_search, self, "spi", NULL);
168 1.2.4.2 ad }
169 1.2.4.2 ad
170 1.2.4.2 ad CFATTACH_DECL(spi, sizeof(struct spi_softc),
171 1.2.4.2 ad spi_match, spi_attach, NULL, NULL);
172 1.2.4.2 ad
173 1.2.4.2 ad /*
174 1.2.4.2 ad * Configure. This should be the first thing that the SPI driver
175 1.2.4.2 ad * should do, to configure which mode (e.g. SPI_MODE_0, which is the
176 1.2.4.2 ad * same as Philips Microwire mode), and speed. If the bus driver
177 1.2.4.2 ad * cannot run fast enough, then it should just configure the fastest
178 1.2.4.2 ad * mode that it can support. If the bus driver cannot run slow
179 1.2.4.2 ad * enough, then the device is incompatible and an error should be
180 1.2.4.2 ad * returned.
181 1.2.4.2 ad */
182 1.2.4.2 ad int
183 1.2.4.2 ad spi_configure(struct spi_handle *sh, int mode, int speed)
184 1.2.4.2 ad {
185 1.2.4.2 ad int s, rv;
186 1.2.4.2 ad struct spi_softc *sc = sh->sh_sc;
187 1.2.4.2 ad struct spi_controller *tag = sh->sh_controller;
188 1.2.4.2 ad
189 1.2.4.2 ad /* ensure that request is compatible with other devices on the bus */
190 1.2.4.2 ad if ((sc->sc_mode >= 0) && (sc->sc_mode != mode))
191 1.2.4.2 ad return EINVAL;
192 1.2.4.2 ad
193 1.2.4.2 ad s = splserial();
194 1.2.4.2 ad /* pick lowest configured speed */
195 1.2.4.2 ad if (speed == 0)
196 1.2.4.2 ad speed = sc->sc_speed;
197 1.2.4.2 ad if (sc->sc_speed)
198 1.2.4.2 ad speed = min(sc->sc_speed, speed);
199 1.2.4.2 ad
200 1.2.4.2 ad rv = (*tag->sct_configure)(tag->sct_cookie, sh->sh_slave,
201 1.2.4.2 ad mode, speed);
202 1.2.4.2 ad
203 1.2.4.2 ad if (rv == 0) {
204 1.2.4.2 ad sc->sc_mode = mode;
205 1.2.4.2 ad sc->sc_speed = speed;
206 1.2.4.2 ad }
207 1.2.4.2 ad splx(s);
208 1.2.4.2 ad return rv;
209 1.2.4.2 ad }
210 1.2.4.2 ad
211 1.2.4.2 ad void
212 1.2.4.2 ad spi_transfer_init(struct spi_transfer *st)
213 1.2.4.2 ad {
214 1.2.4.2 ad
215 1.2.4.2 ad simple_lock_init(&st->st_lock);
216 1.2.4.2 ad st->st_flags = 0;
217 1.2.4.2 ad st->st_errno = 0;
218 1.2.4.2 ad st->st_done = NULL;
219 1.2.4.2 ad st->st_chunks = NULL;
220 1.2.4.2 ad st->st_private = NULL;
221 1.2.4.2 ad st->st_slave = -1;
222 1.2.4.2 ad }
223 1.2.4.2 ad
224 1.2.4.2 ad void
225 1.2.4.2 ad spi_chunk_init(struct spi_chunk *chunk, int cnt, const uint8_t *wptr,
226 1.2.4.2 ad uint8_t *rptr)
227 1.2.4.2 ad {
228 1.2.4.2 ad
229 1.2.4.2 ad chunk->chunk_write = chunk->chunk_wptr = wptr;
230 1.2.4.2 ad chunk->chunk_read = chunk->chunk_read = rptr;
231 1.2.4.2 ad chunk->chunk_rresid = chunk->chunk_wresid = chunk->chunk_count = cnt;
232 1.2.4.2 ad chunk->chunk_next = NULL;
233 1.2.4.2 ad }
234 1.2.4.2 ad
235 1.2.4.2 ad void
236 1.2.4.2 ad spi_transfer_add(struct spi_transfer *st, struct spi_chunk *chunk)
237 1.2.4.2 ad {
238 1.2.4.2 ad struct spi_chunk **cpp;
239 1.2.4.2 ad
240 1.2.4.2 ad /* this is an O(n) insert -- perhaps we should use a simpleq? */
241 1.2.4.2 ad for (cpp = &st->st_chunks; *cpp; cpp = &(*cpp)->chunk_next);
242 1.2.4.2 ad *cpp = chunk;
243 1.2.4.2 ad }
244 1.2.4.2 ad
245 1.2.4.2 ad int
246 1.2.4.2 ad spi_transfer(struct spi_handle *sh, struct spi_transfer *st)
247 1.2.4.2 ad {
248 1.2.4.2 ad struct spi_controller *tag = sh->sh_controller;
249 1.2.4.2 ad struct spi_chunk *chunk;
250 1.2.4.2 ad
251 1.2.4.2 ad /*
252 1.2.4.2 ad * Initialize "resid" counters and pointers, so that callers
253 1.2.4.2 ad * and bus drivers don't have to.
254 1.2.4.2 ad */
255 1.2.4.2 ad for (chunk = st->st_chunks; chunk; chunk = chunk->chunk_next) {
256 1.2.4.2 ad chunk->chunk_wresid = chunk->chunk_rresid = chunk->chunk_count;
257 1.2.4.2 ad chunk->chunk_wptr = chunk->chunk_write;
258 1.2.4.2 ad chunk->chunk_rptr = chunk->chunk_read;
259 1.2.4.2 ad }
260 1.2.4.2 ad
261 1.2.4.2 ad /*
262 1.2.4.2 ad * Match slave to handle's slave.
263 1.2.4.2 ad */
264 1.2.4.2 ad st->st_slave = sh->sh_slave;
265 1.2.4.2 ad
266 1.2.4.2 ad return (*tag->sct_transfer)(tag->sct_cookie, st);
267 1.2.4.2 ad }
268 1.2.4.2 ad
269 1.2.4.2 ad void
270 1.2.4.2 ad spi_wait(struct spi_transfer *st)
271 1.2.4.2 ad {
272 1.2.4.2 ad int s;
273 1.2.4.2 ad
274 1.2.4.2 ad s = splserial();
275 1.2.4.2 ad simple_lock(&st->st_lock);
276 1.2.4.2 ad while (!st->st_flags & SPI_F_DONE) {
277 1.2.4.2 ad ltsleep(st, PWAIT, "spi_wait", 0, &st->st_lock);
278 1.2.4.2 ad }
279 1.2.4.2 ad simple_unlock(&st->st_lock);
280 1.2.4.2 ad splx(s);
281 1.2.4.2 ad }
282 1.2.4.2 ad
283 1.2.4.2 ad void
284 1.2.4.2 ad spi_done(struct spi_transfer *st, int err)
285 1.2.4.2 ad {
286 1.2.4.2 ad int s;
287 1.2.4.2 ad
288 1.2.4.2 ad s = splserial();
289 1.2.4.2 ad
290 1.2.4.2 ad if ((st->st_errno = err) != 0) {
291 1.2.4.2 ad st->st_flags |= SPI_F_ERROR;
292 1.2.4.2 ad }
293 1.2.4.2 ad st->st_flags |= SPI_F_DONE;
294 1.2.4.2 ad if (st->st_done != NULL) {
295 1.2.4.2 ad (*st->st_done)(st);
296 1.2.4.2 ad } else {
297 1.2.4.2 ad
298 1.2.4.2 ad simple_lock(&st->st_lock);
299 1.2.4.2 ad wakeup(st);
300 1.2.4.2 ad simple_unlock(&st->st_lock);
301 1.2.4.2 ad }
302 1.2.4.2 ad splx(s);
303 1.2.4.2 ad }
304 1.2.4.2 ad
305 1.2.4.2 ad /*
306 1.2.4.2 ad * Some convenience routines. These routines block until the work
307 1.2.4.2 ad * is done.
308 1.2.4.2 ad *
309 1.2.4.2 ad * spi_recv - receives data from the bus
310 1.2.4.2 ad *
311 1.2.4.2 ad * spi_send - sends data to the bus
312 1.2.4.2 ad *
313 1.2.4.2 ad * spi_send_recv - sends data to the bus, and then receives. Note that this is
314 1.2.4.2 ad * done synchronously, i.e. send a command and get the response. This is
315 1.2.4.2 ad * not full duplex. If you wnat full duplex, you can't use these convenience
316 1.2.4.2 ad * wrappers.
317 1.2.4.2 ad */
318 1.2.4.2 ad int
319 1.2.4.2 ad spi_recv(struct spi_handle *sh, int cnt, uint8_t *data)
320 1.2.4.2 ad {
321 1.2.4.2 ad struct spi_transfer trans;
322 1.2.4.2 ad struct spi_chunk chunk;
323 1.2.4.2 ad
324 1.2.4.2 ad spi_transfer_init(&trans);
325 1.2.4.2 ad spi_chunk_init(&chunk, cnt, NULL, data);
326 1.2.4.2 ad spi_transfer_add(&trans, &chunk);
327 1.2.4.2 ad
328 1.2.4.2 ad /* enqueue it and wait for it to complete */
329 1.2.4.2 ad spi_transfer(sh, &trans);
330 1.2.4.2 ad spi_wait(&trans);
331 1.2.4.2 ad
332 1.2.4.2 ad if (trans.st_flags & SPI_F_ERROR)
333 1.2.4.2 ad return trans.st_errno;
334 1.2.4.2 ad
335 1.2.4.2 ad return 0;
336 1.2.4.2 ad }
337 1.2.4.2 ad
338 1.2.4.2 ad int
339 1.2.4.2 ad spi_send(struct spi_handle *sh, int cnt, const uint8_t *data)
340 1.2.4.2 ad {
341 1.2.4.2 ad struct spi_transfer trans;
342 1.2.4.2 ad struct spi_chunk chunk;
343 1.2.4.2 ad
344 1.2.4.2 ad spi_transfer_init(&trans);
345 1.2.4.2 ad spi_chunk_init(&chunk, cnt, data, NULL);
346 1.2.4.2 ad spi_transfer_add(&trans, &chunk);
347 1.2.4.2 ad
348 1.2.4.2 ad /* enqueue it and wait for it to complete */
349 1.2.4.2 ad spi_transfer(sh, &trans);
350 1.2.4.2 ad spi_wait(&trans);
351 1.2.4.2 ad
352 1.2.4.2 ad if (trans.st_flags & SPI_F_ERROR)
353 1.2.4.2 ad return trans.st_errno;
354 1.2.4.2 ad
355 1.2.4.2 ad return 0;
356 1.2.4.2 ad }
357 1.2.4.2 ad
358 1.2.4.2 ad int
359 1.2.4.2 ad spi_send_recv(struct spi_handle *sh, int scnt, const uint8_t *snd,
360 1.2.4.2 ad int rcnt, uint8_t *rcv)
361 1.2.4.2 ad {
362 1.2.4.2 ad struct spi_transfer trans;
363 1.2.4.2 ad struct spi_chunk chunk1, chunk2;
364 1.2.4.2 ad
365 1.2.4.2 ad spi_transfer_init(&trans);
366 1.2.4.2 ad spi_chunk_init(&chunk1, scnt, snd, NULL);
367 1.2.4.2 ad spi_chunk_init(&chunk2, rcnt, NULL, rcv);
368 1.2.4.2 ad spi_transfer_add(&trans, &chunk1);
369 1.2.4.2 ad spi_transfer_add(&trans, &chunk2);
370 1.2.4.2 ad
371 1.2.4.2 ad /* enqueue it and wait for it to complete */
372 1.2.4.2 ad spi_transfer(sh, &trans);
373 1.2.4.2 ad spi_wait(&trans);
374 1.2.4.2 ad
375 1.2.4.2 ad if (trans.st_flags & SPI_F_ERROR)
376 1.2.4.2 ad return trans.st_errno;
377 1.2.4.2 ad
378 1.2.4.2 ad return 0;
379 1.2.4.2 ad }
380