xref: /netbsd-src/sys/arch/mips/atheros/dev/arspi.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* $NetBSD: arspi.c,v 1.10 2012/10/27 17:18:02 chs 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.10 2012/10/27 17:18:02 chs Exp $");
46 
47 #include "locators.h"
48 
49 #include <sys/param.h>
50 #include <sys/bus.h>
51 #include <sys/cpu.h>
52 #include <sys/device.h>
53 #include <sys/errno.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/proc.h>
57 #include <sys/systm.h>
58 
59 #include <mips/atheros/include/ar5315reg.h>
60 #include <mips/atheros/include/arbusvar.h>
61 
62 #include <mips/atheros/dev/arspireg.h>
63 
64 #include <dev/spi/spiflash.h>
65 #include <dev/spi/spivar.h>
66 
67 /*
68  * This device is intended only to operate with specific SPI flash
69  * parts, and is not a general purpose SPI host.  (Or at least if it
70  * is, the Linux and eCos sources do not show how to use it as such.)
71  * And lack of documentation on the Atheros SoCs is less than helpful.
72  *
73  * So for now we just "emulate" enough of the host bus framework to
74  * make the SPI flash drivers happy.
75  */
76 
77 struct arspi_job {
78 	uint8_t			job_opcode;
79 	struct spi_chunk	*job_chunk;
80 	uint32_t		job_flags;
81 	uint32_t		job_addr;
82 	uint32_t		job_data;
83 	int			job_rxcnt;
84 	int			job_txcnt;
85 	int			job_addrcnt;
86 	int			job_rresid;
87 	int			job_wresid;
88 };
89 
90 #define	JOB_READ		0x1
91 #define	JOB_WRITE		0x2
92 #define	JOB_LAST		0x4
93 #define	JOB_WAIT		0x8	/* job must wait for WIP bits */
94 #define	JOB_WREN		0x10	/* WREN needed */
95 
96 struct arspi_softc {
97 	struct spi_controller	sc_spi;
98 	void			*sc_ih;
99 	bool			sc_interrupts;
100 
101 	struct spi_transfer	*sc_transfer;
102 	struct spi_chunk	*sc_wchunk;	/* for partial writes */
103 	struct spi_transq	sc_transq;
104 	bus_space_tag_t		sc_st;
105 	bus_space_handle_t	sc_sh;
106 	bus_size_t		sc_size;
107 };
108 
109 #define	STATIC
110 
111 STATIC int arspi_match(device_t, cfdata_t, void *);
112 STATIC void arspi_attach(device_t, device_t, void *);
113 STATIC void arspi_interrupts(device_t);
114 STATIC int arspi_intr(void *);
115 /* SPI service routines */
116 STATIC int arspi_configure(void *, int, int, int);
117 STATIC int arspi_transfer(void *, struct spi_transfer *);
118 /* internal support */
119 STATIC void arspi_poll(struct arspi_softc *);
120 STATIC void arspi_done(struct arspi_softc *, int);
121 STATIC void arspi_sched(struct arspi_softc *);
122 STATIC int arspi_get_byte(struct spi_chunk **, uint8_t *);
123 STATIC int arspi_put_byte(struct spi_chunk **, uint8_t);
124 STATIC int arspi_make_job(struct spi_transfer *);
125 STATIC void arspi_update_job(struct spi_transfer *);
126 STATIC void arspi_finish_job(struct spi_transfer *);
127 
128 
129 CFATTACH_DECL_NEW(arspi, sizeof(struct arspi_softc),
130     arspi_match, arspi_attach, NULL, NULL);
131 
132 #define	GETREG(sc, o)		bus_space_read_4(sc->sc_st, sc->sc_sh, o)
133 #define	PUTREG(sc, o, v)	bus_space_write_4(sc->sc_st, sc->sc_sh, o, v)
134 
135 int
136 arspi_match(device_t parent, cfdata_t cf, void *aux)
137 {
138 	struct arbus_attach_args *aa = aux;
139 
140 	if (strcmp(aa->aa_name, cf->cf_name) != 0)
141 		return 0;
142 	return 1;
143 }
144 
145 void
146 arspi_attach(device_t parent, device_t self, void *aux)
147 {
148 	struct arspi_softc *sc = device_private(self);
149 	struct spibus_attach_args sba;
150 	struct arbus_attach_args *aa = aux;
151 
152 	/*
153 	 * Map registers.
154 	 */
155 	sc->sc_st = aa->aa_bst;
156 	sc->sc_size = aa->aa_size;
157 	if (bus_space_map(sc->sc_st, aa->aa_addr, sc->sc_size, 0,
158 		&sc->sc_sh) != 0) {
159 		printf(": unable to map registers!\n");
160 		return;
161 	}
162 
163 	aprint_normal(": Atheros SPI controller\n");
164 
165 	/*
166 	 * Initialize SPI controller.
167 	 */
168 	sc->sc_spi.sct_cookie = sc;
169 	sc->sc_spi.sct_configure = arspi_configure;
170 	sc->sc_spi.sct_transfer = arspi_transfer;
171 	sc->sc_spi.sct_nslaves = 1;
172 
173 
174 	/*
175 	 * Initialize the queue.
176 	 */
177 	spi_transq_init(&sc->sc_transq);
178 
179 	/*
180 	 * Enable device interrupts.
181 	 */
182 	sc->sc_ih = arbus_intr_establish(aa->aa_cirq, aa->aa_mirq,
183 	    arspi_intr, sc);
184 	if (sc->sc_ih == NULL) {
185 		aprint_error("%s: couldn't establish interrupt\n",
186 		    device_xname(self));
187 		/* just leave it in polled mode */
188 	} else
189 		config_interrupts(self, arspi_interrupts);
190 
191 	/*
192 	 * Initialize and attach bus attach.
193 	 */
194 	sba.sba_controller = &sc->sc_spi;
195 	(void) config_found_ia(self, "spibus", &sba, spibus_print);
196 }
197 
198 void
199 arspi_interrupts(device_t self)
200 {
201 	/*
202 	 * we never leave polling mode, because, apparently, we
203 	 * are missing some data about how to drive the SPI in interrupt
204 	 * mode.
205 	 */
206 #if 0
207 	struct arspi_softc *sc = device_private(self);
208 	int	s;
209 
210 	s = splbio();
211 	sc->sc_interrupts = true;
212 	splx(s);
213 #endif
214 }
215 
216 int
217 arspi_intr(void *arg)
218 {
219 	struct arspi_softc *sc = arg;
220 
221 	while (GETREG(sc, ARSPI_REG_CTL) & ARSPI_CTL_BUSY);
222 
223 	arspi_done(sc, 0);
224 
225 	return 1;
226 }
227 
228 void
229 arspi_poll(struct arspi_softc *sc)
230 {
231 
232 	while (sc->sc_transfer) {
233 		arspi_intr(sc);
234 	}
235 }
236 
237 int
238 arspi_configure(void *cookie, int slave, int mode, int speed)
239 {
240 
241 	/*
242 	 * We don't support the full SPI protocol, and hopefully the
243 	 * firmware has programmed a reasonable mode already.  So
244 	 * just a couple of quick sanity checks, then bail.
245 	 */
246 	if ((mode != 0) || (slave != 0))
247 		return EINVAL;
248 
249 	return 0;
250 }
251 
252 int
253 arspi_transfer(void *cookie, struct spi_transfer *st)
254 {
255 	struct arspi_softc *sc = cookie;
256 	int rv;
257 	int s;
258 
259 	st->st_busprivate = NULL;
260 	if ((rv = arspi_make_job(st)) != 0) {
261 		if (st->st_busprivate) {
262 			free(st->st_busprivate, M_DEVBUF);
263 			st->st_busprivate = NULL;
264 		}
265 		spi_done(st, rv);
266 		return rv;
267 	}
268 
269 	s = splbio();
270 	spi_transq_enqueue(&sc->sc_transq, st);
271 	if (sc->sc_transfer == NULL) {
272 		arspi_sched(sc);
273 		if (!sc->sc_interrupts)
274 			arspi_poll(sc);
275 	}
276 	splx(s);
277 	return 0;
278 }
279 
280 void
281 arspi_sched(struct arspi_softc *sc)
282 {
283 	struct spi_transfer *st;
284 	struct arspi_job *job;
285 	uint32_t ctl, cnt;
286 
287 	for (;;) {
288 		if ((st = sc->sc_transfer) == NULL) {
289 			if ((st = spi_transq_first(&sc->sc_transq)) == NULL) {
290 				/* no work left to do */
291 				break;
292 			}
293 			spi_transq_dequeue(&sc->sc_transq);
294 			sc->sc_transfer = st;
295 		}
296 
297 		arspi_update_job(st);
298 		job = st->st_busprivate;
299 
300 		/* there shouldn't be anything running, but ensure it */
301 		do {
302 			ctl = GETREG(sc, ARSPI_REG_CTL);
303 		}  while (ctl & ARSPI_CTL_BUSY);
304 		/* clear all of the tx and rx bits */
305 		ctl &= ~(ARSPI_CTL_TXCNT_MASK | ARSPI_CTL_RXCNT_MASK);
306 
307 		if (job->job_flags & JOB_WAIT) {
308 			PUTREG(sc, ARSPI_REG_OPCODE, SPIFLASH_CMD_RDSR);
309 			/* only the opcode for tx */
310 			ctl |= (1 << ARSPI_CTL_TXCNT_SHIFT);
311 			/* and one rx byte */
312 			ctl |= (1 << ARSPI_CTL_RXCNT_SHIFT);
313 		} else if (job->job_flags & JOB_WREN) {
314 			PUTREG(sc, ARSPI_REG_OPCODE, SPIFLASH_CMD_WREN);
315 			/* just the opcode */
316 			ctl |= (1 << ARSPI_CTL_TXCNT_SHIFT);
317 			/* no rx bytes */
318 		} else {
319 			/* set the data */
320 			PUTREG(sc, ARSPI_REG_DATA, job->job_data);
321 
322 			/* set the opcode and the address */
323 			PUTREG(sc, ARSPI_REG_OPCODE, job->job_opcode |
324 			    (job->job_addr << 8));
325 
326 			/* now set txcnt */
327 			cnt = 1;	/* opcode */
328 			cnt += job->job_addrcnt + job->job_txcnt;
329 			ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT);
330 
331 			/* now set rxcnt */
332 			cnt = job->job_rxcnt;
333 			ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT);
334 		}
335 
336 		/* set the start bit */
337 		ctl |= ARSPI_CTL_START;
338 
339 		PUTREG(sc, ARSPI_REG_CTL, ctl);
340 		break;
341 	}
342 }
343 
344 void
345 arspi_done(struct arspi_softc *sc, int err)
346 {
347 	struct spi_transfer *st;
348 	struct arspi_job *job;
349 
350 	if ((st = sc->sc_transfer) != NULL) {
351 		job = st->st_busprivate;
352 
353 		if (job->job_flags & JOB_WAIT) {
354 			if (err == 0) {
355 				if ((GETREG(sc, ARSPI_REG_DATA) &
356 				    SPIFLASH_SR_BUSY) == 0) {
357 					/* intermediate wait done */
358 					job->job_flags &= ~JOB_WAIT;
359 					goto done;
360 				}
361 			}
362 		} else if (job->job_flags & JOB_WREN) {
363 			if (err == 0) {
364 				job->job_flags &= ~JOB_WREN;
365 				goto done;
366 			}
367 		} else if (err == 0) {
368 			/*
369 			 * When breaking up write jobs, we have to wait until
370 			 * the WIP bit is clear, and we have to separately
371 			 * send WREN for each chunk.  These flags facilitate
372 			 * that.
373 			 */
374 			if (job->job_flags & JOB_WRITE)
375 				job->job_flags |= (JOB_WAIT | JOB_WREN);
376 			job->job_data = GETREG(sc, ARSPI_REG_DATA);
377 			arspi_finish_job(st);
378 		}
379 
380 		if (err || (job->job_flags & JOB_LAST)) {
381 			sc->sc_transfer = NULL;
382 			st->st_busprivate = NULL;
383 			spi_done(st, err);
384 			free(job, M_DEVBUF);
385 		}
386 	}
387 done:
388 	arspi_sched(sc);
389 }
390 
391 int
392 arspi_get_byte(struct spi_chunk **chunkp, uint8_t *bytep)
393 {
394 	struct spi_chunk *chunk;
395 
396 	chunk = *chunkp;
397 
398 	/* skip leading empty (or already consumed) chunks */
399 	while (chunk && chunk->chunk_wresid == 0)
400 		chunk = chunk->chunk_next;
401 
402 	if (chunk == NULL) {
403 		return ENODATA;
404 	}
405 
406 	/*
407 	 * chunk must be write only.  SPI flash doesn't support
408 	 * any full duplex operations.
409 	 */
410 	if ((chunk->chunk_rptr) || !(chunk->chunk_wptr)) {
411 		return EINVAL;
412 	}
413 
414 	*bytep = *chunk->chunk_wptr;
415 	chunk->chunk_wptr++;
416 	chunk->chunk_wresid--;
417 	chunk->chunk_rresid--;
418 	/* clearing wptr and rptr makes sanity checks later easier */
419 	if (chunk->chunk_wresid == 0)
420 		chunk->chunk_wptr = NULL;
421 	if (chunk->chunk_rresid == 0)
422 		chunk->chunk_rptr = NULL;
423 	while (chunk && chunk->chunk_wresid == 0)
424 		chunk = chunk->chunk_next;
425 
426 	*chunkp = chunk;
427 	return 0;
428 }
429 
430 int
431 arspi_put_byte(struct spi_chunk **chunkp, uint8_t byte)
432 {
433 	struct spi_chunk *chunk;
434 
435 	chunk = *chunkp;
436 
437 	/* skip leading empty (or already consumed) chunks */
438 	while (chunk && chunk->chunk_rresid == 0)
439 		chunk = chunk->chunk_next;
440 
441 	if (chunk == NULL) {
442 		return EOVERFLOW;
443 	}
444 
445 	/*
446 	 * chunk must be read only.  SPI flash doesn't support
447 	 * any full duplex operations.
448 	 */
449 	if ((chunk->chunk_wptr) || !(chunk->chunk_rptr)) {
450 		return EINVAL;
451 	}
452 
453 	*chunk->chunk_rptr = byte;
454 	chunk->chunk_rptr++;
455 	chunk->chunk_wresid--;	/* technically this was done at send time */
456 	chunk->chunk_rresid--;
457 	while (chunk && chunk->chunk_rresid == 0)
458 		chunk = chunk->chunk_next;
459 
460 	*chunkp = chunk;
461 	return 0;
462 }
463 
464 int
465 arspi_make_job(struct spi_transfer *st)
466 {
467 	struct arspi_job *job;
468 	struct spi_chunk *chunk;
469 	uint8_t byte;
470 	int i, rv;
471 
472 	job = malloc(sizeof (struct arspi_job), M_DEVBUF, M_ZERO);
473 	if (job == NULL) {
474 		return ENOMEM;
475 	}
476 
477 	st->st_busprivate = job;
478 
479 	/* skip any leading empty chunks (should not be any!) */
480 	chunk = st->st_chunks;
481 
482 	/* get transfer opcode */
483 	if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
484 		return rv;
485 
486 	job->job_opcode = byte;
487 	switch (job->job_opcode) {
488 	case SPIFLASH_CMD_WREN:
489 	case SPIFLASH_CMD_WRDI:
490 	case SPIFLASH_CMD_CHIPERASE:
491 		break;
492 	case SPIFLASH_CMD_RDJI:
493 		job->job_rxcnt = 3;
494 		break;
495 	case SPIFLASH_CMD_RDSR:
496 		job->job_rxcnt = 1;
497 		break;
498 	case SPIFLASH_CMD_WRSR:
499 		/*
500 		 * is this in data, or in address?  stick it in data
501 		 * for now.
502 		 */
503 		job->job_txcnt = 1;
504 		break;
505 	case SPIFLASH_CMD_RDID:
506 		job->job_addrcnt = 3;	/* 3 dummy bytes */
507 		job->job_rxcnt = 1;
508 		break;
509 	case SPIFLASH_CMD_ERASE:
510 		job->job_addrcnt = 3;
511 		break;
512 	case SPIFLASH_CMD_READ:
513 		job->job_addrcnt = 3;
514 		job->job_flags |= JOB_READ;
515 		break;
516 	case SPIFLASH_CMD_PROGRAM:
517 		job->job_addrcnt = 3;
518 		job->job_flags |= JOB_WRITE;
519 		break;
520 	case SPIFLASH_CMD_READFAST:
521 		/*
522 		 * This is a pain in the arse to support, so we will
523 		 * rewrite as an ordinary read.  But later, after we
524 		 * obtain the address.
525 		 */
526 		job->job_addrcnt = 3;	/* 3 address */
527 		job->job_flags |= JOB_READ;
528 		break;
529 	default:
530 		return EINVAL;
531 	}
532 
533 	for (i = 0; i < job->job_addrcnt; i++) {
534 		if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
535 			return rv;
536 		job->job_addr <<= 8;
537 		job->job_addr |= byte;
538 	}
539 
540 
541 	if (job->job_opcode == SPIFLASH_CMD_READFAST) {
542 		/* eat the dummy timing byte */
543 		if ((rv = arspi_get_byte(&chunk, &byte)) != 0)
544 			return rv;
545 		/* rewrite this as a read */
546 		job->job_opcode = SPIFLASH_CMD_READ;
547 	}
548 
549 	job->job_chunk = chunk;
550 
551 	/*
552 	 * Now quickly check a few other things.   Namely, we are not
553 	 * allowed to have both READ and WRITE.
554 	 */
555 	for (chunk = job->job_chunk; chunk; chunk = chunk->chunk_next) {
556 		if (chunk->chunk_wptr) {
557 			job->job_wresid += chunk->chunk_wresid;
558 		}
559 		if (chunk->chunk_rptr) {
560 			job->job_rresid += chunk->chunk_rresid;
561 		}
562 	}
563 
564 	if (job->job_rresid && job->job_wresid) {
565 		return EINVAL;
566 	}
567 
568 	return 0;
569 }
570 
571 /*
572  * NB: The Atheros SPI controller runs in little endian mode. So all
573  * data accesses must be swapped appropriately.
574  *
575  * The controller auto-swaps read accesses done through the mapped memory
576  * region, but when using SPI directly, we have to do the right thing to
577  * swap to or from little endian.
578  */
579 
580 void
581 arspi_update_job(struct spi_transfer *st)
582 {
583 	struct arspi_job *job = st->st_busprivate;
584 	uint8_t byte;
585 	int i;
586 
587 	if (job->job_flags & (JOB_WAIT|JOB_WREN))
588 		return;
589 
590 	job->job_rxcnt = 0;
591 	job->job_txcnt = 0;
592 	job->job_data = 0;
593 
594 	job->job_txcnt = min(job->job_wresid, 4);
595 	job->job_rxcnt = min(job->job_rresid, 4);
596 
597 	job->job_wresid -= job->job_txcnt;
598 	job->job_rresid -= job->job_rxcnt;
599 
600 	for (i = 0; i < job->job_txcnt; i++) {
601 		arspi_get_byte(&job->job_chunk, &byte);
602 		job->job_data |= (byte << (i * 8));
603 	}
604 
605 	if ((!job->job_wresid) && (!job->job_rresid)) {
606 		job->job_flags |= JOB_LAST;
607 	}
608 }
609 
610 void
611 arspi_finish_job(struct spi_transfer *st)
612 {
613 	struct arspi_job *job = st->st_busprivate;
614 	uint8_t	byte;
615 	int i;
616 
617 	job->job_addr += job->job_rxcnt;
618 	job->job_addr += job->job_txcnt;
619 	for (i = 0; i < job->job_rxcnt; i++) {
620 		byte = job->job_data & 0xff;
621 		job->job_data >>= 8;
622 		arspi_put_byte(&job->job_chunk, byte);
623 	}
624 }
625 
626