spiflash.c revision 1.5
1/* $NetBSD: spiflash.c,v 1.5 2007/07/19 00:00:09 dyoung 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: spiflash.c,v 1.5 2007/07/19 00:00:09 dyoung Exp $");
46
47#include <sys/param.h>
48#include <sys/conf.h>
49#include <sys/proc.h>
50#include <sys/systm.h>
51#include <sys/device.h>
52#include <sys/kernel.h>
53#include <sys/file.h>
54#include <sys/ioctl.h>
55#include <sys/disk.h>
56#include <sys/disklabel.h>
57#include <sys/buf.h>
58#include <sys/bufq.h>
59#include <sys/uio.h>
60#include <sys/kthread.h>
61#include <sys/malloc.h>
62#include <sys/errno.h>
63
64#include <dev/spi/spivar.h>
65#include <dev/spi/spiflash.h>
66
67/*
68 * This is an MI block driver for SPI flash devices.  It could probably be
69 * converted to some more generic framework, if someone wanted to create one
70 * for NOR flashes.  Note that some flashes have the ability to handle
71 * interrupts.
72 */
73
74struct spiflash_softc {
75	struct device		sc_dev;
76	struct disk		sc_dk;
77
78	struct spiflash_hw_if	sc_hw;
79	void			*sc_cookie;
80
81	const char		*sc_name;
82	struct spi_handle	*sc_handle;
83	int			sc_device_size;
84	int			sc_write_size;
85	int			sc_erase_size;
86	int			sc_read_size;
87	int			sc_device_blks;
88
89	struct bufq_state	*sc_waitq;
90	struct bufq_state	*sc_workq;
91	struct bufq_state	*sc_doneq;
92	lwp_t			*sc_thread;
93};
94
95#define	sc_getname	sc_hw.sf_getname
96#define	sc_gethandle	sc_hw.sf_gethandle
97#define	sc_getsize	sc_hw.sf_getsize
98#define	sc_getflags	sc_hw.sf_getflags
99#define	sc_erase	sc_hw.sf_erase
100#define	sc_write	sc_hw.sf_write
101#define	sc_read		sc_hw.sf_read
102#define	sc_getstatus	sc_hw.sf_getstatus
103#define	sc_setstatus	sc_hw.sf_setstatus
104
105struct spiflash_attach_args {
106	const struct spiflash_hw_if	*hw;
107	void				*cookie;
108};
109
110#define	STATIC
111STATIC int spiflash_match(struct device *, struct cfdata *, void *);
112STATIC void spiflash_attach(struct device *, struct device *, void *);
113STATIC int spiflash_print(void *, const char *);
114STATIC int spiflash_common_erase(spiflash_handle_t, size_t, size_t);
115STATIC int spiflash_common_write(spiflash_handle_t, size_t, size_t,
116    const uint8_t *);
117STATIC int spiflash_common_read(spiflash_handle_t, size_t, size_t, uint8_t *);
118STATIC void spiflash_process_done(spiflash_handle_t, int);
119STATIC void spiflash_process_read(spiflash_handle_t);
120STATIC void spiflash_process_write(spiflash_handle_t);
121STATIC void spiflash_thread(void *);
122STATIC int spiflash_nsectors(spiflash_handle_t, struct buf *);
123STATIC int spiflash_nsectors(spiflash_handle_t, struct buf *);
124STATIC int spiflash_sector(spiflash_handle_t, struct buf *);
125
126CFATTACH_DECL(spiflash, sizeof(struct spiflash_softc),
127	      spiflash_match, spiflash_attach, NULL, NULL);
128
129#ifdef	SPIFLASH_DEBUG
130#define	DPRINTF(x)	do { printf x; } while (0/*CONSTCOND*/)
131#else
132#define	DPRINTF(x)	do {  } while (0/*CONSTCOND*/)
133#endif
134
135extern struct cfdriver spiflash_cd;
136
137dev_type_open(spiflash_open);
138dev_type_close(spiflash_close);
139dev_type_read(spiflash_read);
140dev_type_write(spiflash_write);
141dev_type_ioctl(spiflash_ioctl);
142dev_type_strategy(spiflash_strategy);
143
144const struct bdevsw spiflash_bdevsw = {
145	.d_open = spiflash_open,
146	.d_close = spiflash_close,
147	.d_strategy = spiflash_strategy,
148	.d_ioctl = spiflash_ioctl,
149	.d_dump = nodump,
150	.d_psize = nosize,
151	.d_flag = D_DISK,
152};
153
154const struct cdevsw spiflash_cdevsw = {
155	.d_open = spiflash_open,
156	.d_close = spiflash_close,
157	.d_read = spiflash_read,
158	.d_write = spiflash_write,
159	.d_ioctl = spiflash_ioctl,
160	.d_stop = nostop,
161	.d_tty = notty,
162	.d_poll = nopoll,
163	.d_mmap = nommap,
164	.d_kqfilter = nokqfilter,
165	.d_flag = D_DISK,
166};
167
168static struct dkdriver spiflash_dkdriver = { spiflash_strategy, NULL };
169
170spiflash_handle_t
171spiflash_attach_mi(const struct spiflash_hw_if *hw, void *cookie,
172    struct device *dev)
173{
174	struct spiflash_attach_args sfa;
175	sfa.hw = hw;
176	sfa.cookie = cookie;
177
178	return (spiflash_handle_t)config_found(dev, &sfa, spiflash_print);
179}
180
181int
182spiflash_print(void *aux, const char *pnp)
183{
184	if (pnp != NULL)
185		printf("spiflash at %s\n", pnp);
186
187	return UNCONF;
188}
189
190int
191spiflash_match(struct device *parent, struct cfdata *cf, void *aux)
192{
193
194	return 1;
195}
196
197void
198spiflash_attach(struct device *parent, struct device *self, void *aux)
199{
200	struct spiflash_softc *sc = device_private(self);
201	struct spiflash_attach_args *sfa = aux;
202	void *cookie = sfa->cookie;
203
204	sc->sc_hw = *sfa->hw;
205	sc->sc_cookie = cookie;
206	sc->sc_name = sc->sc_getname(cookie);
207	sc->sc_handle = sc->sc_gethandle(cookie);
208	sc->sc_device_size = sc->sc_getsize(cookie, SPIFLASH_SIZE_DEVICE);
209	sc->sc_erase_size = sc->sc_getsize(cookie, SPIFLASH_SIZE_ERASE);
210	sc->sc_write_size = sc->sc_getsize(cookie, SPIFLASH_SIZE_WRITE);
211	sc->sc_read_size = sc->sc_getsize(cookie, SPIFLASH_SIZE_READ);
212	sc->sc_device_blks = sc->sc_device_size / DEV_BSIZE;
213
214	if (sc->sc_read == NULL)
215		sc->sc_read = spiflash_common_read;
216	if (sc->sc_write == NULL)
217		sc->sc_write = spiflash_common_write;
218	if (sc->sc_erase == NULL)
219		sc->sc_erase = spiflash_common_erase;
220
221	aprint_naive(": SPI flash\n");
222	aprint_normal(": %s SPI flash\n", sc->sc_name);
223	/* XXX: note that this has to change for boot-sectored flash */
224	aprint_normal("%s: %d KB, %d sectors of %d KB each\n",
225	    sc->sc_dev.dv_xname, sc->sc_device_size / 1024,
226	    sc->sc_device_size / sc->sc_erase_size,
227	    sc->sc_erase_size / 1024);
228
229	/* first-come first-served strategy works best for us */
230	bufq_alloc(&sc->sc_waitq, "fcfs", BUFQ_SORT_RAWBLOCK);
231	bufq_alloc(&sc->sc_workq, "fcfs", BUFQ_SORT_RAWBLOCK);
232	bufq_alloc(&sc->sc_doneq, "fcfs", BUFQ_SORT_RAWBLOCK);
233
234	sc->sc_dk.dk_driver = &spiflash_dkdriver;
235	sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
236
237	disk_attach(&sc->sc_dk);
238
239	/* arrange to allocate the kthread */
240	kthread_create(PRI_NONE, 0, NULL, spiflash_thread, sc,
241	    &sc->sc_thread, "spiflash");
242}
243
244int
245spiflash_open(dev_t dev, int flags, int mode, struct lwp *l)
246{
247	spiflash_handle_t sc;
248
249	if ((sc = device_lookup(&spiflash_cd, DISKUNIT(dev))) == NULL)
250		return ENXIO;
251
252	/*
253	 * XXX: We need to handle partitions here.  The problem is
254	 * that it isn't entirely clear to me how to deal with this.
255	 * There are devices that could be used "in the raw" with a
256	 * NetBSD label, but then you get into devices that have other
257	 * kinds of data on them -- some have VxWorks data, some have
258	 * RedBoot data, and some have other contraints -- for example
259	 * some devices might have a portion that is read-only,
260	 * whereas others might have a portion that is read-write.
261	 *
262	 * For now we just permit access to the entire device.
263	 */
264	return 0;
265}
266
267int
268spiflash_close(dev_t dev, int flags, int mode, struct lwp *l)
269{
270	spiflash_handle_t sc;
271
272	if ((sc = device_lookup(&spiflash_cd, DISKUNIT(dev))) == NULL)
273		return ENXIO;
274
275	return 0;
276}
277
278int
279spiflash_read(dev_t dev, struct uio *uio, int ioflag)
280{
281
282	return physio(spiflash_strategy, NULL, dev, B_READ, minphys, uio);
283}
284
285int
286spiflash_write(dev_t dev, struct uio *uio, int ioflag)
287{
288
289	return physio(spiflash_strategy, NULL, dev, B_WRITE, minphys, uio);
290}
291
292int
293spiflash_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
294{
295	spiflash_handle_t sc;
296
297	if ((sc = device_lookup(&spiflash_cd, DISKUNIT(dev))) == NULL)
298		return ENXIO;
299
300	return EINVAL;
301}
302
303void
304spiflash_strategy(struct buf *bp)
305{
306	spiflash_handle_t sc;
307	int	s;
308
309	sc = device_lookup(&spiflash_cd, DISKUNIT(bp->b_dev));
310	if (sc == NULL) {
311		bp->b_error = ENXIO;
312		bp->b_flags |= B_ERROR;
313		biodone(bp);
314		return;
315	}
316
317	if (((bp->b_bcount % sc->sc_write_size) != 0) ||
318	    (bp->b_blkno < 0)) {
319		bp->b_error = EINVAL;
320		bp->b_flags |= B_ERROR;
321		biodone(bp);
322		return;
323	}
324
325	/* no work? */
326	if (bp->b_bcount == 0) {
327		biodone(bp);
328		return;
329	}
330
331	if (bounds_check_with_mediasize(bp, DEV_BSIZE,
332		sc->sc_device_blks) <= 0) {
333		biodone(bp);
334		return;
335	}
336
337	bp->b_resid = bp->b_bcount;
338
339	/* all ready, hand off to thread for async processing */
340	s = splbio();
341	BUFQ_PUT(sc->sc_waitq, bp);
342	wakeup(&sc->sc_thread);
343	splx(s);
344}
345
346void
347spiflash_process_done(spiflash_handle_t sc, int err)
348{
349	struct buf	*bp;
350	int		cnt = 0;
351	int		flag = 0;
352
353	while ((bp = BUFQ_GET(sc->sc_doneq)) != NULL) {
354		flag = bp->b_flags & B_READ;
355		if ((bp->b_error = err) != 0)
356			bp->b_flags |= B_ERROR;
357		else
358			bp->b_resid = 0;
359		cnt += bp->b_bcount - bp->b_resid;
360		biodone(bp);
361	}
362	disk_unbusy(&sc->sc_dk, cnt, flag);
363}
364
365void
366spiflash_process_read(spiflash_handle_t sc)
367{
368	struct buf	*bp;
369	int		err = 0;
370
371	disk_busy(&sc->sc_dk);
372	while ((bp = BUFQ_GET(sc->sc_workq)) != NULL) {
373		size_t addr = bp->b_blkno * DEV_BSIZE;
374		uint8_t *data = bp->b_data;
375		int cnt = bp->b_resid;
376
377		BUFQ_PUT(sc->sc_doneq, bp);
378
379		DPRINTF(("read from addr %x, cnt %d\n", (unsigned)addr, cnt));
380
381		if ((err = sc->sc_read(sc, addr, cnt, data)) != 0) {
382			/* error occurred, fail all pending workq bufs */
383			bufq_move(sc->sc_doneq, sc->sc_workq);
384			break;
385		}
386
387		bp->b_resid -= cnt;
388		data += cnt;
389		addr += cnt;
390	}
391	spiflash_process_done(sc, err);
392}
393
394void
395spiflash_process_write(spiflash_handle_t sc)
396{
397	int	len;
398	size_t	base;
399	daddr_t	blkno;
400	uint8_t	*save;
401	int	err = 0, neederase = 0;
402	struct buf *bp;
403
404	/*
405	 * due to other considerations, we are guaranteed that
406	 * we will only have multiple buffers if they are all in
407	 * the same erase sector.  Therefore we never need to look
408	 * beyond the first block to determine how much data we need
409	 * to save.
410	 */
411
412	bp = BUFQ_PEEK(sc->sc_workq);
413	len = spiflash_nsectors(sc, bp)  * sc->sc_erase_size;
414	blkno = bp->b_blkno;
415	base = (blkno * DEV_BSIZE) & ~ (sc->sc_erase_size - 1);
416
417	/* get ourself a scratch buffer */
418	save = malloc(len, M_DEVBUF, M_WAITOK);
419
420	disk_busy(&sc->sc_dk);
421	/* read in as much of the data as we need */
422	DPRINTF(("reading in %d bytes\n", len));
423	if ((err = sc->sc_read(sc, base, len, save)) != 0) {
424		bufq_move(sc->sc_doneq, sc->sc_workq);
425		spiflash_process_done(sc, err);
426		return;
427	}
428
429	/*
430	 * now coalesce the writes into the save area, but also
431	 * check to see if we need to do an erase
432	 */
433	while ((bp = BUFQ_GET(sc->sc_workq)) != NULL) {
434		uint8_t	*data, *dst;
435		int resid = bp->b_resid;
436
437		DPRINTF(("coalesce write, blkno %x, count %d, resid %d\n",
438			    (unsigned)bp->b_blkno, bp->b_bcount, resid));
439
440		data = bp->b_data;
441		dst = save + (bp->b_blkno - blkno) * DEV_BSIZE;
442
443		/*
444		 * NOR flash bits.  We can clear a bit, but we cannot
445		 * set a bit, without erasing.  This should help reduce
446		 * unnecessary erases.
447		 */
448		while (resid) {
449			if ((*data) & ~(*dst))
450				neederase = 1;
451			*dst++ = *data++;
452			resid--;
453		}
454
455		BUFQ_PUT(sc->sc_doneq, bp);
456	}
457
458	/*
459	 * do the erase, if we need to.
460	 */
461	if (neederase) {
462		DPRINTF(("erasing from %x - %x\n", base, base + len));
463		if ((err = sc->sc_erase(sc, base, len)) != 0) {
464			spiflash_process_done(sc, err);
465			return;
466		}
467	}
468
469	/*
470	 * now write our save area, and finish up.
471	 */
472	DPRINTF(("flashing %d bytes to %x from %x\n", len,
473		    base, (unsigned)save));
474	err = sc->sc_write(sc, base, len, save);
475	spiflash_process_done(sc, err);
476}
477
478
479int
480spiflash_nsectors(spiflash_handle_t sc, struct buf *bp)
481{
482	unsigned	addr, sector;
483
484	addr = bp->b_blkno * DEV_BSIZE;
485	sector = addr / sc->sc_erase_size;
486
487	addr += bp->b_bcount;
488	addr--;
489	return (((addr / sc->sc_erase_size)  - sector) + 1);
490}
491
492int
493spiflash_sector(spiflash_handle_t sc, struct buf *bp)
494{
495	unsigned	addr, sector;
496
497	addr = bp->b_blkno * DEV_BSIZE;
498	sector = addr / sc->sc_erase_size;
499
500	/* if it spans multiple blocks, error it */
501	addr += bp->b_bcount;
502	addr--;
503	if (sector != (addr / sc->sc_erase_size))
504		return -1;
505
506	return sector;
507}
508
509void
510spiflash_thread(void *arg)
511{
512	spiflash_handle_t sc = arg;
513	struct buf	*bp;
514	int		s;
515	int		sector;
516
517	s = splbio();
518	for (;;) {
519		if ((bp = BUFQ_GET(sc->sc_waitq)) == NULL) {
520			tsleep(&sc->sc_thread, PRIBIO, "spiflash_thread", 0);
521			continue;
522		}
523
524		BUFQ_PUT(sc->sc_workq, bp);
525
526		if (bp->b_flags & B_READ) {
527			/* just do the read */
528			spiflash_process_read(sc);
529			continue;
530		}
531
532		/*
533		 * Because writing a flash filesystem is particularly
534		 * painful, involving erase, modify, write, we prefer
535		 * to coalesce writes to the same sector together.
536		 */
537
538		sector = spiflash_sector(sc, bp);
539
540		/*
541		 * if the write spans multiple sectors, skip
542		 * coalescing.  (It would be nice if we could break
543		 * these up.  minphys is honored for read/write, but
544		 * not necessarily for bread.)
545		 */
546		if (sector < 0)
547			goto dowrite;
548
549		while ((bp = BUFQ_PEEK(sc->sc_waitq)) != NULL) {
550			/* can't deal with read requests! */
551			if (bp->b_flags & B_READ)
552				break;
553
554			/* is it for the same sector? */
555			if (spiflash_sector(sc, bp) != sector)
556				break;
557
558			bp = BUFQ_GET(sc->sc_waitq);
559			BUFQ_PUT(sc->sc_workq, bp);
560		}
561
562	dowrite:
563		spiflash_process_write(sc);
564	}
565}
566/*
567 * SPI flash common implementation.
568 */
569
570/*
571 * Most devices take on the order of 1 second for each block that they
572 * delete.
573 */
574int
575spiflash_common_erase(spiflash_handle_t sc, size_t start, size_t size)
576{
577	int		rv;
578
579	if ((start % sc->sc_erase_size) || (size % sc->sc_erase_size))
580		return EINVAL;
581
582	/* the second test is to test against wrap */
583	if ((start > sc->sc_device_size) ||
584	    ((start + size) > sc->sc_device_size))
585		return EINVAL;
586
587	/*
588	 * XXX: check protection status?  Requires master table mapping
589	 * sectors to status bits, and so forth.
590	 */
591
592	while (size) {
593		if ((rv = spiflash_write_enable(sc)) != 0) {
594			spiflash_write_disable(sc);
595			return rv;
596		}
597		if ((rv = spiflash_cmd(sc, SPIFLASH_CMD_ERASE, 3, start, 0,
598			 NULL, NULL)) != 0) {
599			spiflash_write_disable(sc);
600			return rv;
601		}
602
603		/*
604		 * The devices I have all say typical for sector erase
605		 * is ~1sec.  We check ten times that often.  (There
606		 * is no way to interrupt on this.)
607		 */
608		if ((rv = spiflash_wait(sc, hz / 10)) != 0)
609			return rv;
610
611		start += sc->sc_erase_size;
612		size -= sc->sc_erase_size;
613
614		/* NB: according to the docs I have, the write enable
615		 * is automatically cleared upon completion of an erase
616		 * command, so there is no need to explicitly disable it.
617		 */
618	}
619
620	return 0;
621}
622
623int
624spiflash_common_write(spiflash_handle_t sc, size_t start, size_t size,
625    const uint8_t *data)
626{
627	int		rv;
628
629	if ((start % sc->sc_write_size) || (size % sc->sc_write_size))
630		return EINVAL;
631
632	while (size) {
633		int cnt;
634
635		if ((rv = spiflash_write_enable(sc)) != 0) {
636			spiflash_write_disable(sc);
637			return rv;
638		}
639
640		cnt = min(size, sc->sc_write_size);
641		if ((rv = spiflash_cmd(sc, SPIFLASH_CMD_PROGRAM, 3, start,
642			 cnt, data, NULL)) != 0) {
643			spiflash_write_disable(sc);
644			return rv;
645		}
646
647		/*
648		 * It seems that most devices can write bits fairly
649		 * quickly.  For example, one part I have access to
650		 * takes ~5msec to process the entire 256 byte page.
651		 * Probably this should be modified to cope with
652		 * device-specific timing, and maybe also take into
653		 * account systems with higher values of HZ (which
654		 * could benefit from sleeping.)
655		 */
656		if ((rv = spiflash_wait(sc, 0)) != 0)
657			return rv;
658
659		data += cnt;
660		start += cnt;
661		size -= cnt;
662	}
663
664	return 0;
665}
666
667int
668spiflash_common_read(spiflash_handle_t sc, size_t start, size_t size,
669    uint8_t *data)
670{
671	int		rv;
672
673	while (size) {
674		int cnt;
675
676		if (sc->sc_read_size > 0)
677			cnt = min(size, sc->sc_read_size);
678		else
679			cnt = size;
680
681		if ((rv = spiflash_cmd(sc, SPIFLASH_CMD_READ, 3, start,
682			 cnt, NULL, data)) != 0) {
683			return rv;
684		}
685
686		start += cnt;
687		size -= cnt;
688	}
689
690	return 0;
691}
692
693/* read status register */
694int
695spiflash_read_status(spiflash_handle_t sc, uint8_t *sr)
696{
697
698	return spiflash_cmd(sc, SPIFLASH_CMD_RDSR, 0, 0, 1, NULL, sr);
699}
700
701int
702spiflash_write_enable(spiflash_handle_t sc)
703{
704
705	return spiflash_cmd(sc, SPIFLASH_CMD_WREN, 0, 0, 0, NULL, NULL);
706}
707
708int
709spiflash_write_disable(spiflash_handle_t sc)
710{
711
712	return spiflash_cmd(sc, SPIFLASH_CMD_WRDI, 0, 0, 0, NULL, NULL);
713}
714
715int
716spiflash_cmd(spiflash_handle_t sc, uint8_t cmd,
717    size_t addrlen, uint32_t addr,
718    size_t cnt, const uint8_t *wdata, uint8_t *rdata)
719{
720	struct spi_transfer	trans;
721	struct spi_chunk	chunk1, chunk2;
722	char buf[4];
723	int i;
724
725	buf[0] = cmd;
726
727	if (addrlen > 3)
728		return EINVAL;
729
730	for (i = addrlen; i > 0; i--) {
731		buf[i] = addr & 0xff;
732		addr >>= 8;
733	}
734	spi_transfer_init(&trans);
735	spi_chunk_init(&chunk1, addrlen + 1, buf, NULL);
736	spi_transfer_add(&trans, &chunk1);
737	if (cnt) {
738		spi_chunk_init(&chunk2, cnt, wdata, rdata);
739		spi_transfer_add(&trans, &chunk2);
740	}
741
742	spi_transfer(sc->sc_handle, &trans);
743	spi_wait(&trans);
744
745	if (trans.st_flags & SPI_F_ERROR)
746		return trans.st_errno;
747	return 0;
748}
749
750int
751spiflash_wait(spiflash_handle_t sc, int tmo)
752{
753	int	rv;
754	uint8_t	sr;
755
756	for (;;) {
757		if ((rv = spiflash_read_status(sc, &sr)) != 0)
758			return rv;
759
760		if ((sr & SPIFLASH_SR_BUSY) == 0)
761			break;
762		/*
763		 * The devices I have all say typical for sector
764		 * erase is ~1sec.  We check time times that often.
765		 * (There is no way to interrupt on this.)
766		 */
767		if (tmo)
768			tsleep(&sr, PWAIT, "spiflash_wait", tmo);
769	}
770	return 0;
771}
772