xref: /netbsd-src/sys/arch/mips/atheros/dev/arspi.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /* $NetBSD: arspi.c,v 1.5 2007/02/28 04:21:53 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2006 Urbana-Champaign Independent Media Center.
5  * Copyright (c) 2006 Garrett D'Amore.
6  * All rights reserved.
7  *
8  * Portions of this code were written by Garrett D'Amore for the
9  * Champaign-Urbana Community Wireless Network Project.
10  *
11  * Redistribution and use in source and binary forms, with or
12  * without modification, are permitted provided that the following
13  * conditions are met:
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.
28  *
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.
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: arspi.c,v 1.5 2007/02/28 04:21:53 thorpej Exp $");
46 
47 #include "locators.h"
48 
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>
55 #include <sys/proc.h>
56 #include <sys/queue.h>
57 
58 #include <machine/bus.h>
59 #include <machine/cpu.h>
60 
61 #include <mips/atheros/include/ar5315reg.h>
62 #include <mips/atheros/include/ar531xvar.h>
63 #include <mips/atheros/include/arbusvar.h>
64 
65 #include <mips/atheros/dev/arspireg.h>
66 
67 #include <dev/spi/spiflash.h>
68 #include <dev/spi/spivar.h>
69 
70 /*
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.
75  *
76  * So for now we just "emulate" enough of the host bus framework to
77  * make the SPI flash drivers happy.
78  */
79 
80 struct arspi_job {
81 	uint8_t			job_opcode;
82 	struct spi_chunk	*job_chunk;
83 	uint32_t		job_flags;
84 	uint32_t		job_addr;
85 	uint32_t		job_data;
86 	int			job_rxcnt;
87 	int			job_txcnt;
88 	int			job_addrcnt;
89 	int			job_rresid;
90 	int			job_wresid;
91 };
92 
93 #define	JOB_READ		0x1
94 #define	JOB_WRITE		0x2
95 #define	JOB_LAST		0x4
96 #define	JOB_WAIT		0x8	/* job must wait for WIP bits */
97 #define	JOB_WREN		0x10	/* WREN needed */
98 
99 struct arspi_softc {
100 	struct device		sc_dev;
101 	struct spi_controller	sc_spi;
102 	void			*sc_ih;
103 	bool			sc_interrupts;
104 
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;
110 	bus_size_t		sc_size;
111 };
112 
113 #define	STATIC
114 
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 *);
131 
132 
133 CFATTACH_DECL(arspi, sizeof(struct arspi_softc),
134     arspi_match, arspi_attach, NULL, NULL);
135 
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)
138 
139 int
140 arspi_match(struct device *parent, struct cfdata *cf, void *aux)
141 {
142 	struct arbus_attach_args *aa = aux;
143 
144 	if (strcmp(aa->aa_name, cf->cf_name) != 0)
145 		return 0;
146 	return 1;
147 }
148 
149 void
150 arspi_attach(struct device *parent, struct device *self, void *aux)
151 {
152 	struct arspi_softc *sc = device_private(self);
153 	struct spibus_attach_args sba;
154 	struct arbus_attach_args *aa = aux;
155 
156 	/*
157 	 * Map registers.
158 	 */
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,
162 		&sc->sc_sh) != 0) {
163 		printf(": unable to map registers!\n");
164 		return;
165 	}
166 
167 	aprint_normal(": Atheros SPI controller\n");
168 
169 	/*
170 	 * Initialize SPI controller.
171 	 */
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;
176 
177 
178 	/*
179 	 * Initialize the queue.
180 	 */
181 	spi_transq_init(&sc->sc_transq);
182 
183 	/*
184 	 * Enable device interrupts.
185 	 */
186 	sc->sc_ih = arbus_intr_establish(aa->aa_cirq, aa->aa_mirq,
187 	    arspi_intr, sc);
188 	if (sc->sc_ih == NULL) {
189 		aprint_error("%s: couldn't establish interrupt\n",
190 		    device_xname(self));
191 		/* just leave it in polled mode */
192 	} else
193 		config_interrupts(self, arspi_interrupts);
194 
195 	/*
196 	 * Initialize and attach bus attach.
197 	 */
198 	sba.sba_controller = &sc->sc_spi;
199 	(void) config_found_ia(&sc->sc_dev, "spibus", &sba, spibus_print);
200 }
201 
202 void
203 arspi_interrupts(struct device *self)
204 {
205 	/*
206 	 * we never leave polling mode, because, apparently, we
207 	 * are missing some data about how to drive the SPI in interrupt
208 	 * mode.
209 	 */
210 #if 0
211 	struct arspi_softc *sc = device_private(self);
212 	int	s;
213 
214 	s = splserial();
215 	sc->sc_interrupts = true;
216 	splx(s);
217 #endif
218 }
219 
220 int
221 arspi_intr(void *arg)
222 {
223 	struct arspi_softc *sc = arg;
224 
225 	while (GETREG(sc, ARSPI_REG_CTL) & ARSPI_CTL_BUSY);
226 
227 	arspi_done(sc, 0);
228 
229 	return 1;
230 }
231 
232 void
233 arspi_poll(struct arspi_softc *sc)
234 {
235 
236 	while (sc->sc_transfer) {
237 		arspi_intr(sc);
238 	}
239 }
240 
241 int
242 arspi_configure(void *cookie, int slave, int mode, int speed)
243 {
244 
245 	/*
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.
249 	 */
250 	if ((mode != 0) || (slave != 0))
251 		return EINVAL;
252 
253 	return 0;
254 }
255 
256 int
257 arspi_transfer(void *cookie, struct spi_transfer *st)
258 {
259 	struct arspi_softc *sc = cookie;
260 	int rv;
261 	int s;
262 
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;
268 		}
269 		spi_done(st, rv);
270 		return rv;
271 	}
272 
273 	s = splserial();
274 	spi_transq_enqueue(&sc->sc_transq, st);
275 	if (sc->sc_transfer == NULL) {
276 		arspi_sched(sc);
277 		if (!sc->sc_interrupts)
278 			arspi_poll(sc);
279 	}
280 	splx(s);
281 	return 0;
282 }
283 
284 void
285 arspi_sched(struct arspi_softc *sc)
286 {
287 	struct spi_transfer *st;
288 	struct arspi_job *job;
289 	uint32_t ctl, cnt;
290 
291 	for (;;) {
292 		if ((st = sc->sc_transfer) == NULL) {
293 			if ((st = spi_transq_first(&sc->sc_transq)) == NULL) {
294 				/* no work left to do */
295 				break;
296 			}
297 			spi_transq_dequeue(&sc->sc_transq);
298 			sc->sc_transfer = st;
299 		}
300 
301 		arspi_update_job(st);
302 		job = st->st_busprivate;
303 
304 		/* there shouldn't be anything running, but ensure it */
305 		do {
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);
310 
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);
321 			/* no rx bytes */
322 		} else {
323 			/* set the data */
324 			PUTREG(sc, ARSPI_REG_DATA, job->job_data);
325 
326 			/* set the opcode and the address */
327 			PUTREG(sc, ARSPI_REG_OPCODE, job->job_opcode |
328 			    (job->job_addr << 8));
329 
330 			/* now set txcnt */
331 			cnt = 1;	/* opcode */
332 			cnt += job->job_addrcnt + job->job_txcnt;
333 			ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT);
334 
335 			/* now set rxcnt */
336 			cnt = job->job_rxcnt;
337 			ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT);
338 		}
339 
340 		/* set the start bit */
341 		ctl |= ARSPI_CTL_START;
342 
343 		PUTREG(sc, ARSPI_REG_CTL, ctl);
344 		break;
345 	}
346 }
347 
348 void
349 arspi_done(struct arspi_softc *sc, int err)
350 {
351 	struct spi_transfer *st;
352 	struct arspi_job *job;
353 
354 	if ((st = sc->sc_transfer) != NULL) {
355 		job = st->st_busprivate;
356 
357 		if (job->job_flags & JOB_WAIT) {
358 			if (err == 0) {
359 				if ((GETREG(sc, ARSPI_REG_DATA) &
360 				    SPIFLASH_SR_BUSY) == 0) {
361 					/* intermediate wait done */
362 					job->job_flags &= ~JOB_WAIT;
363 					goto done;
364 				}
365 			}
366 		} else if (job->job_flags & JOB_WREN) {
367 			if (err == 0) {
368 				job->job_flags &= ~JOB_WREN;
369 				goto done;
370 			}
371 		} else if (err == 0) {
372 			/*
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
376 			 * that.
377 			 */
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);
382 		}
383 
384 		if (err || (job->job_flags & JOB_LAST)) {
385 			sc->sc_transfer = NULL;
386 			st->st_busprivate = NULL;
387 			spi_done(st, err);
388 			free(job, M_DEVBUF);
389 		}
390 	}
391 done:
392 	arspi_sched(sc);
393 }
394 
395 int
396 arspi_get_byte(struct spi_chunk **chunkp, uint8_t *bytep)
397 {
398 	struct spi_chunk *chunk;
399 
400 	chunk = *chunkp;
401 
402 	/* skip leading empty (or already consumed) chunks */
403 	while (chunk && chunk->chunk_wresid == 0)
404 		chunk = chunk->chunk_next;
405 
406 	if (chunk == NULL) {
407 		return ENODATA;
408 	}
409 
410 	/*
411 	 * chunk must be write only.  SPI flash doesn't support
412 	 * any full duplex operations.
413 	 */
414 	if ((chunk->chunk_rptr) || !(chunk->chunk_wptr)) {
415 		return EINVAL;
416 	}
417 
418 	*bytep = *chunk->chunk_wptr;
419 	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;
429 
430 	*chunkp = chunk;
431 	return 0;
432 }
433 
434 int
435 arspi_put_byte(struct spi_chunk **chunkp, uint8_t byte)
436 {
437 	struct spi_chunk *chunk;
438 
439 	chunk = *chunkp;
440 
441 	/* skip leading empty (or already consumed) chunks */
442 	while (chunk && chunk->chunk_rresid == 0)
443 		chunk = chunk->chunk_next;
444 
445 	if (chunk == NULL) {
446 		return EOVERFLOW;
447 	}
448 
449 	/*
450 	 * chunk must be read only.  SPI flash doesn't support
451 	 * any full duplex operations.
452 	 */
453 	if ((chunk->chunk_wptr) || !(chunk->chunk_rptr)) {
454 		return EINVAL;
455 	}
456 
457 	*chunk->chunk_rptr = byte;
458 	chunk->chunk_rptr++;
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;
463 
464 	*chunkp = chunk;
465 	return 0;
466 }
467 
468 int
469 arspi_make_job(struct spi_transfer *st)
470 {
471 	struct arspi_job *job;
472 	struct spi_chunk *chunk;
473 	uint8_t byte;
474 	int i, rv;
475 
476 	job = malloc(sizeof (struct arspi_job), M_DEVBUF, M_ZERO);
477 	if (job == NULL) {
478 		return ENOMEM;
479 	}
480 
481 	st->st_busprivate = job;
482 
483 	/* skip any leading empty chunks (should not be any!) */
484 	chunk = st->st_chunks;
485 
486 	/* get transfer opcode */
487 	if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
488 		return rv;
489 
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:
495 		break;
496 	case SPIFLASH_CMD_RDJI:
497 		job->job_rxcnt = 3;
498 		break;
499 	case SPIFLASH_CMD_RDSR:
500 		job->job_rxcnt = 1;
501 		break;
502 	case SPIFLASH_CMD_WRSR:
503 		/*
504 		 * is this in data, or in address?  stick it in data
505 		 * for now.
506 		 */
507 		job->job_txcnt = 1;
508 		break;
509 	case SPIFLASH_CMD_RDID:
510 		job->job_addrcnt = 3;	/* 3 dummy bytes */
511 		job->job_rxcnt = 1;
512 		break;
513 	case SPIFLASH_CMD_ERASE:
514 		job->job_addrcnt = 3;
515 		break;
516 	case SPIFLASH_CMD_READ:
517 		job->job_addrcnt = 3;
518 		job->job_flags |= JOB_READ;
519 		break;
520 	case SPIFLASH_CMD_PROGRAM:
521 		job->job_addrcnt = 3;
522 		job->job_flags |= JOB_WRITE;
523 		break;
524 	case SPIFLASH_CMD_READFAST:
525 		/*
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.
529 		 */
530 		job->job_addrcnt = 3;	/* 3 address */
531 		job->job_flags |= JOB_READ;
532 		break;
533 	default:
534 		return EINVAL;
535 	}
536 
537 	for (i = 0; i < job->job_addrcnt; i++) {
538 		if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
539 			return rv;
540 		job->job_addr <<= 8;
541 		job->job_addr |= byte;
542 	}
543 
544 
545 	if (job->job_opcode == SPIFLASH_CMD_READFAST) {
546 		/* eat the dummy timing byte */
547 		if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
548 			return rv;
549 		/* rewrite this as a read */
550 		job->job_opcode = SPIFLASH_CMD_READ;
551 	}
552 
553 	job->job_chunk = chunk;
554 
555 	/*
556 	 * Now quickly check a few other things.   Namely, we are not
557 	 * allowed to have both READ and WRITE.
558 	 */
559 	for (chunk = job->job_chunk; chunk; chunk = chunk->chunk_next) {
560 		if (chunk->chunk_wptr) {
561 			job->job_wresid += chunk->chunk_wresid;
562 		}
563 		if (chunk->chunk_rptr) {
564 			job->job_rresid += chunk->chunk_rresid;
565 		}
566 	}
567 
568 	if (job->job_rresid && job->job_wresid) {
569 		return EINVAL;
570 	}
571 
572 	return 0;
573 }
574 
575 /*
576  * NB: The Atheros SPI controller runs in little endian mode. So all
577  * data accesses must be swapped appropriately.
578  *
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.
582  */
583 
584 void
585 arspi_update_job(struct spi_transfer *st)
586 {
587 	struct arspi_job *job = st->st_busprivate;
588 	uint8_t byte;
589 	int i;
590 
591 	if (job->job_flags & (JOB_WAIT|JOB_WREN))
592 		return;
593 
594 	job->job_rxcnt = 0;
595 	job->job_txcnt = 0;
596 	job->job_data = 0;
597 
598 	job->job_txcnt = min(job->job_wresid, 4);
599 	job->job_rxcnt = min(job->job_rresid, 4);
600 
601 	job->job_wresid -= job->job_txcnt;
602 	job->job_rresid -= job->job_rxcnt;
603 
604 	for (i = 0; i < job->job_txcnt; i++) {
605 		arspi_get_byte(&job->job_chunk, &byte);
606 		job->job_data |= (byte << (i * 8));
607 	}
608 
609 	if ((!job->job_wresid) && (!job->job_rresid)) {
610 		job->job_flags |= JOB_LAST;
611 	}
612 }
613 
614 void
615 arspi_finish_job(struct spi_transfer *st)
616 {
617 	struct arspi_job *job = st->st_busprivate;
618 	uint8_t	byte;
619 	int i;
620 
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;
625 		job->job_data >>= 8;
626 		arspi_put_byte(&job->job_chunk, byte);
627 	}
628 }
629 
630