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