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