1 /* $NetBSD: arspi.c,v 1.4 2007/02/21 22:59:47 thorpej Exp $ */
4 * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
5 * Copyright (c) 2006 Garrett D'Amore.
8 * Portions of this code were written by Garrett D'Amore for the
9 * Champaign-Urbana Community Wireless Network Project.
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgements:
22 * This product includes software developed by the Urbana-Champaign
23 * Independent Media Center.
24 * This product includes software developed by Garrett D'Amore.
25 * 4. Urbana-Champaign Independent Media Center's name and Garrett
26 * D'Amore's name may not be used to endorse or promote products
27 * derived from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT
30 * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT
34 * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: arspi.c,v 1.4 2007/02/21 22:59:47 thorpej Exp $");
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/device.h>
53 #include <sys/errno.h>
54 #include <sys/malloc.h>
56 #include <sys/queue.h>
58 #include <machine/bus.h>
59 #include <machine/cpu.h>
61 #include <mips/atheros/include/ar5315reg.h>
62 #include <mips/atheros/include/ar531xvar.h>
63 #include <mips/atheros/include/arbusvar.h>
65 #include <mips/atheros/dev/arspireg.h>
67 #include <dev/spi/spiflash.h>
68 #include <dev/spi/spivar.h>
71 * This device is intended only to operate with specific SPI flash
72 * parts, and is not a general purpose SPI host. (Or at least if it
73 * is, the Linux and eCos sources do not show how to use it as such.)
74 * And lack of documentation on the Atheros SoCs is less than helpful.
76 * So for now we just "emulate" enough of the host bus framework to
77 * make the SPI flash drivers happy.
82 struct spi_chunk
*job_chunk
;
96 #define JOB_WAIT 0x8 /* job must wait for WIP bits */
97 #define JOB_WREN 0x10 /* WREN needed */
100 struct device sc_dev
;
101 struct spi_controller sc_spi
;
105 struct spi_transfer
*sc_transfer
;
106 struct spi_chunk
*sc_wchunk
; /* for partial writes */
107 struct spi_transq sc_transq
;
108 bus_space_tag_t sc_st
;
109 bus_space_handle_t sc_sh
;
115 STATIC
int arspi_match(struct device
*, struct cfdata
*, void *);
116 STATIC
void arspi_attach(struct device
*, struct device
*, void *);
117 STATIC
void arspi_interrupts(struct device
*);
118 STATIC
int arspi_intr(void *);
119 /* SPI service routines */
120 STATIC
int arspi_configure(void *, int, int, int);
121 STATIC
int arspi_transfer(void *, struct spi_transfer
*);
122 /* internal support */
123 STATIC
void arspi_poll(struct arspi_softc
*);
124 STATIC
void arspi_done(struct arspi_softc
*, int);
125 STATIC
void arspi_sched(struct arspi_softc
*);
126 STATIC
int arspi_get_byte(struct spi_chunk
**, uint8_t *);
127 STATIC
int arspi_put_byte(struct spi_chunk
**, uint8_t);
128 STATIC
int arspi_make_job(struct spi_transfer
*);
129 STATIC
void arspi_update_job(struct spi_transfer
*);
130 STATIC
void arspi_finish_job(struct spi_transfer
*);
133 CFATTACH_DECL(arspi
, sizeof(struct arspi_softc
),
134 arspi_match
, arspi_attach
, NULL
, NULL
);
136 #define GETREG(sc, o) bus_space_read_4(sc->sc_st, sc->sc_sh, o)
137 #define PUTREG(sc, o, v) bus_space_write_4(sc->sc_st, sc->sc_sh, o, v)
140 arspi_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
142 struct arbus_attach_args
*aa
= aux
;
144 if (strcmp(aa
->aa_name
, cf
->cf_name
) != 0)
150 arspi_attach(struct device
*parent
, struct device
*self
, void *aux
)
152 struct arspi_softc
*sc
= device_private(self
);
153 struct spibus_attach_args sba
;
154 struct arbus_attach_args
*aa
= aux
;
159 sc
->sc_st
= aa
->aa_bst
;
160 sc
->sc_size
= aa
->aa_size
;
161 if (bus_space_map(sc
->sc_st
, aa
->aa_addr
, sc
->sc_size
, 0,
163 printf(": unable to map registers!\n");
167 aprint_normal(": Atheros SPI controller\n");
170 * Initialize SPI controller.
172 sc
->sc_spi
.sct_cookie
= sc
;
173 sc
->sc_spi
.sct_configure
= arspi_configure
;
174 sc
->sc_spi
.sct_transfer
= arspi_transfer
;
175 sc
->sc_spi
.sct_nslaves
= 1;
179 * Initialize the queue.
181 spi_transq_init(&sc
->sc_transq
);
184 * Enable device interrupts.
186 sc
->sc_ih
= arbus_intr_establish(aa
->aa_cirq
, aa
->aa_mirq
,
188 if (sc
->sc_ih
== NULL
) {
189 aprint_error("%s: couldn't establish interrupt\n",
191 /* just leave it in polled mode */
193 config_interrupts(self
, arspi_interrupts
);
196 * Initialize and attach bus attach.
198 sba
.sba_controller
= &sc
->sc_spi
;
199 (void) config_found_ia(&sc
->sc_dev
, "spibus", &sba
, spibus_print
);
203 arspi_interrupts(struct device
*self
)
206 * we never leave polling mode, because, apparently, we
207 * are missing some data about how to drive the SPI in interrupt
211 struct arspi_softc
*sc
= device_private(self
);
215 sc
->sc_interrupts
= true;
221 arspi_intr(void *arg
)
223 struct arspi_softc
*sc
= arg
;
225 while (GETREG(sc
, ARSPI_REG_CTL
) & ARSPI_CTL_BUSY
);
233 arspi_poll(struct arspi_softc
*sc
)
236 while (sc
->sc_transfer
) {
242 arspi_configure(void *cookie
, int slave
, int mode
, int speed
)
246 * We don't support the full SPI protocol, and hopefully the
247 * firmware has programmed a reasonable mode already. So
248 * just a couple of quick sanity checks, then bail.
250 if ((mode
!= 0) || (slave
!= 0))
257 arspi_transfer(void *cookie
, struct spi_transfer
*st
)
259 struct arspi_softc
*sc
= cookie
;
263 st
->st_busprivate
= NULL
;
264 if ((rv
= arspi_make_job(st
)) != 0) {
265 if (st
->st_busprivate
) {
266 free(st
->st_busprivate
, M_DEVBUF
);
267 st
->st_busprivate
= NULL
;
274 spi_transq_enqueue(&sc
->sc_transq
, st
);
275 if (sc
->sc_transfer
== NULL
) {
277 if (!sc
->sc_interrupts
)
285 arspi_sched(struct arspi_softc
*sc
)
287 struct spi_transfer
*st
;
288 struct arspi_job
*job
;
292 if ((st
= sc
->sc_transfer
) == NULL
) {
293 if ((st
= spi_transq_first(&sc
->sc_transq
)) == NULL
) {
294 /* no work left to do */
297 spi_transq_dequeue(&sc
->sc_transq
);
298 sc
->sc_transfer
= st
;
301 arspi_update_job(st
);
302 job
= st
->st_busprivate
;
304 /* there shouldn't be anything running, but ensure it */
306 ctl
= GETREG(sc
, ARSPI_REG_CTL
);
307 } while (ctl
& ARSPI_CTL_BUSY
);
308 /* clear all of the tx and rx bits */
309 ctl
&= ~(ARSPI_CTL_TXCNT_MASK
| ARSPI_CTL_RXCNT_MASK
);
311 if (job
->job_flags
& JOB_WAIT
) {
312 PUTREG(sc
, ARSPI_REG_OPCODE
, SPIFLASH_CMD_RDSR
);
313 /* only the opcode for tx */
314 ctl
|= (1 << ARSPI_CTL_TXCNT_SHIFT
);
315 /* and one rx byte */
316 ctl
|= (1 << ARSPI_CTL_RXCNT_SHIFT
);
317 } else if (job
->job_flags
& JOB_WREN
) {
318 PUTREG(sc
, ARSPI_REG_OPCODE
, SPIFLASH_CMD_WREN
);
319 /* just the opcode */
320 ctl
|= (1 << ARSPI_CTL_TXCNT_SHIFT
);
324 PUTREG(sc
, ARSPI_REG_DATA
, job
->job_data
);
326 /* set the opcode and the address */
327 PUTREG(sc
, ARSPI_REG_OPCODE
, job
->job_opcode
|
328 (job
->job_addr
<< 8));
331 cnt
= 1; /* opcode */
332 cnt
+= job
->job_addrcnt
+ job
->job_txcnt
;
333 ctl
|= (cnt
<< ARSPI_CTL_TXCNT_SHIFT
);
336 cnt
= job
->job_rxcnt
;
337 ctl
|= (cnt
<< ARSPI_CTL_RXCNT_SHIFT
);
340 /* set the start bit */
341 ctl
|= ARSPI_CTL_START
;
343 PUTREG(sc
, ARSPI_REG_CTL
, ctl
);
349 arspi_done(struct arspi_softc
*sc
, int err
)
351 struct spi_transfer
*st
;
352 struct arspi_job
*job
;
354 if ((st
= sc
->sc_transfer
) != NULL
) {
355 job
= st
->st_busprivate
;
357 if (job
->job_flags
& JOB_WAIT
) {
359 if ((GETREG(sc
, ARSPI_REG_DATA
) &
360 SPIFLASH_SR_BUSY
) == 0) {
361 /* intermediate wait done */
362 job
->job_flags
&= ~JOB_WAIT
;
366 } else if (job
->job_flags
& JOB_WREN
) {
368 job
->job_flags
&= ~JOB_WREN
;
371 } else if (err
== 0) {
373 * When breaking up write jobs, we have to wait until
374 * the WIP bit is clear, and we have to separately
375 * send WREN for each chunk. These flags facilitate
378 if (job
->job_flags
& JOB_WRITE
)
379 job
->job_flags
|= (JOB_WAIT
| JOB_WREN
);
380 job
->job_data
= GETREG(sc
, ARSPI_REG_DATA
);
381 arspi_finish_job(st
);
384 if (err
|| (job
->job_flags
& JOB_LAST
)) {
385 sc
->sc_transfer
= NULL
;
386 st
->st_busprivate
= NULL
;
396 arspi_get_byte(struct spi_chunk
**chunkp
, uint8_t *bytep
)
398 struct spi_chunk
*chunk
;
402 /* skip leading empty (or already consumed) chunks */
403 while (chunk
&& chunk
->chunk_wresid
== 0)
404 chunk
= chunk
->chunk_next
;
411 * chunk must be write only. SPI flash doesn't support
412 * any full duplex operations.
414 if ((chunk
->chunk_rptr
) || !(chunk
->chunk_wptr
)) {
418 *bytep
= *chunk
->chunk_wptr
;
420 chunk
->chunk_wresid
--;
421 chunk
->chunk_rresid
--;
422 /* clearing wptr and rptr makes sanity checks later easier */
423 if (chunk
->chunk_wresid
== 0)
424 chunk
->chunk_wptr
= NULL
;
425 if (chunk
->chunk_rresid
== 0)
426 chunk
->chunk_rptr
= NULL
;
427 while (chunk
&& chunk
->chunk_wresid
== 0)
428 chunk
= chunk
->chunk_next
;
435 arspi_put_byte(struct spi_chunk
**chunkp
, uint8_t byte
)
437 struct spi_chunk
*chunk
;
441 /* skip leading empty (or already consumed) chunks */
442 while (chunk
&& chunk
->chunk_rresid
== 0)
443 chunk
= chunk
->chunk_next
;
450 * chunk must be read only. SPI flash doesn't support
451 * any full duplex operations.
453 if ((chunk
->chunk_wptr
) || !(chunk
->chunk_rptr
)) {
457 *chunk
->chunk_rptr
= byte
;
459 chunk
->chunk_wresid
--; /* technically this was done at send time */
460 chunk
->chunk_rresid
--;
461 while (chunk
&& chunk
->chunk_rresid
== 0)
462 chunk
= chunk
->chunk_next
;
469 arspi_make_job(struct spi_transfer
*st
)
471 struct arspi_job
*job
;
472 struct spi_chunk
*chunk
;
476 job
= malloc(sizeof (struct arspi_job
), M_DEVBUF
, M_ZERO
);
481 st
->st_busprivate
= job
;
483 /* skip any leading empty chunks (should not be any!) */
484 chunk
= st
->st_chunks
;
486 /* get transfer opcode */
487 if ((rv
= arspi_get_byte(&chunk
, &byte
)) != 0)
490 job
->job_opcode
= byte
;
491 switch (job
->job_opcode
) {
492 case SPIFLASH_CMD_WREN
:
493 case SPIFLASH_CMD_WRDI
:
494 case SPIFLASH_CMD_CHIPERASE
:
496 case SPIFLASH_CMD_RDJI
:
499 case SPIFLASH_CMD_RDSR
:
502 case SPIFLASH_CMD_WRSR
:
504 * is this in data, or in address? stick it in data
509 case SPIFLASH_CMD_RDID
:
510 job
->job_addrcnt
= 3; /* 3 dummy bytes */
513 case SPIFLASH_CMD_ERASE
:
514 job
->job_addrcnt
= 3;
516 case SPIFLASH_CMD_READ
:
517 job
->job_addrcnt
= 3;
518 job
->job_flags
|= JOB_READ
;
520 case SPIFLASH_CMD_PROGRAM
:
521 job
->job_addrcnt
= 3;
522 job
->job_flags
|= JOB_WRITE
;
524 case SPIFLASH_CMD_READFAST
:
526 * This is a pain in the arse to support, so we will
527 * rewrite as an ordinary read. But later, after we
528 * obtain the address.
530 job
->job_addrcnt
= 3; /* 3 address */
531 job
->job_flags
|= JOB_READ
;
537 for (i
= 0; i
< job
->job_addrcnt
; i
++) {
538 if ((rv
= arspi_get_byte(&chunk
, &byte
)) != 0)
541 job
->job_addr
|= byte
;
545 if (job
->job_opcode
== SPIFLASH_CMD_READFAST
) {
546 /* eat the dummy timing byte */
547 if ((rv
= arspi_get_byte(&chunk
, &byte
)) != 0)
549 /* rewrite this as a read */
550 job
->job_opcode
= SPIFLASH_CMD_READ
;
553 job
->job_chunk
= chunk
;
556 * Now quickly check a few other things. Namely, we are not
557 * allowed to have both READ and WRITE.
559 for (chunk
= job
->job_chunk
; chunk
; chunk
= chunk
->chunk_next
) {
560 if (chunk
->chunk_wptr
) {
561 job
->job_wresid
+= chunk
->chunk_wresid
;
563 if (chunk
->chunk_rptr
) {
564 job
->job_rresid
+= chunk
->chunk_rresid
;
568 if (job
->job_rresid
&& job
->job_wresid
) {
576 * NB: The Atheros SPI controller runs in little endian mode. So all
577 * data accesses must be swapped appropriately.
579 * The controller auto-swaps read accesses done through the mapped memory
580 * region, but when using SPI directly, we have to do the right thing to
581 * swap to or from little endian.
585 arspi_update_job(struct spi_transfer
*st
)
587 struct arspi_job
*job
= st
->st_busprivate
;
591 if (job
->job_flags
& (JOB_WAIT
|JOB_WREN
))
598 job
->job_txcnt
= min(job
->job_wresid
, 4);
599 job
->job_rxcnt
= min(job
->job_rresid
, 4);
601 job
->job_wresid
-= job
->job_txcnt
;
602 job
->job_rresid
-= job
->job_rxcnt
;
604 for (i
= 0; i
< job
->job_txcnt
; i
++) {
605 arspi_get_byte(&job
->job_chunk
, &byte
);
606 job
->job_data
|= (byte
<< (i
* 8));
609 if ((!job
->job_wresid
) && (!job
->job_rresid
)) {
610 job
->job_flags
|= JOB_LAST
;
615 arspi_finish_job(struct spi_transfer
*st
)
617 struct arspi_job
*job
= st
->st_busprivate
;
621 job
->job_addr
+= job
->job_rxcnt
;
622 job
->job_addr
+= job
->job_txcnt
;
623 for (i
= 0; i
< job
->job_rxcnt
; i
++) {
624 byte
= job
->job_data
& 0xff;
626 arspi_put_byte(&job
->job_chunk
, byte
);