xref: /freebsd/sys/dev/flash/w25n.c (revision 89e3c2d27ab426e1edf326d470318d75d8be5e37)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2022 Adrian Chadd <adrian@FreeBSD.org>.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 
29 #include "opt_platform.h"
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bio.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/kernel.h>
37 #include <sys/kthread.h>
38 #include <sys/lock.h>
39 #include <sys/mbuf.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/mutex.h>
43 #include <geom/geom_disk.h>
44 
45 #ifdef FDT
46 #include <dev/fdt/fdt_common.h>
47 #include <dev/ofw/ofw_bus_subr.h>
48 #include <dev/ofw/openfirm.h>
49 #endif
50 
51 #include <dev/spibus/spi.h>
52 #include "spibus_if.h"
53 
54 #include <dev/flash/w25nreg.h>
55 
56 #define	W25N_SECTORSIZE	512
57 
58 struct w25n_flash_ident
59 {
60 	const char	*name;
61 	uint8_t		manufacturer_id;
62 	uint16_t	device_id;
63 	unsigned int	sectorsize;
64 	unsigned int	sectorcount;
65 	unsigned int	erasesize;
66 	unsigned int	flags;
67 };
68 
69 struct w25n_softc
70 {
71 	device_t	sc_dev;
72 	device_t	sc_parent;
73 	uint8_t		sc_manufacturer_id;
74 	uint16_t	sc_device_id;
75 	unsigned int	sc_erasesize;
76 	struct mtx	sc_mtx;
77 	struct disk	*sc_disk;
78 	struct proc	*sc_p;
79 	struct bio_queue_head sc_bio_queue;
80 	unsigned int	sc_flags;
81 	unsigned int	sc_taskstate;
82 };
83 
84 #define	TSTATE_STOPPED		0
85 #define	TSTATE_STOPPING		1
86 #define	TSTATE_RUNNING		2
87 
88 #define W25N_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
89 #define	W25N_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
90 #define W25N_LOCK_INIT(_sc) \
91 	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
92 	    "w25n", MTX_DEF)
93 #define W25N_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
94 #define W25N_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
95 #define W25N_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
96 
97 /* disk routines */
98 static int w25n_open(struct disk *dp);
99 static int w25n_close(struct disk *dp);
100 static int w25n_ioctl(struct disk *, u_long, void *, int, struct thread *);
101 static void w25n_strategy(struct bio *bp);
102 static int w25n_getattr(struct bio *bp);
103 static void w25n_task(void *arg);
104 
105 #define	FL_NONE		0x00000000
106 
107 static struct w25n_flash_ident flash_devices[] = {
108 
109 	{ "w25n01gv",	0xef, 0xaa21, 2048, 64 * 1024, 128 * 1024, FL_NONE },
110 };
111 
112 static int
w25n_read_status_register(struct w25n_softc * sc,uint8_t reg,uint8_t * retval)113 w25n_read_status_register(struct w25n_softc *sc, uint8_t reg,
114     uint8_t *retval)
115 {
116 	uint8_t txBuf[3], rxBuf[3];
117 	struct spi_command cmd;
118 	int err;
119 
120 	memset(&cmd, 0, sizeof(cmd));
121 
122 	txBuf[0] = CMD_READ_STATUS;
123 	txBuf[1] = reg;
124 	cmd.tx_cmd = txBuf;
125 	cmd.rx_cmd = rxBuf;
126 	cmd.rx_cmd_sz = 3;
127 	cmd.tx_cmd_sz = 3;
128 	err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
129 	if (err != 0)
130 		return (err);
131 	*retval = rxBuf[2];
132 	return (0);
133 }
134 
135 static int
w25n_wait_for_device_ready(struct w25n_softc * sc)136 w25n_wait_for_device_ready(struct w25n_softc *sc)
137 {
138 	int err;
139 	uint8_t val;
140 
141 	do {
142 		err = w25n_read_status_register(sc, STATUS_REG_3, &val);
143 	} while (err == 0 && (val & STATUS_REG_3_BUSY));
144 
145 	return (err);
146 }
147 
148 static int
w25n_set_page_address(struct w25n_softc * sc,uint16_t page_idx)149 w25n_set_page_address(struct w25n_softc *sc, uint16_t page_idx)
150 {
151 	uint8_t txBuf[4], rxBuf[4];
152 	struct spi_command cmd;
153 	int err;
154 
155 	txBuf[0] = CMD_PAGE_DATA_READ;
156 	txBuf[1] = 0; /* dummy */
157 	txBuf[2] = (page_idx >> 8) & 0xff;
158 	txBuf[3] = (page_idx >> 0) & 0xff;
159 	cmd.tx_cmd = txBuf;
160 	cmd.rx_cmd = rxBuf;
161 	cmd.rx_cmd_sz = 4;
162 	cmd.tx_cmd_sz = 4;
163 	err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
164 	if (err != 0)
165 		return (err);
166 	return (0);
167 }
168 
169 static struct w25n_flash_ident*
w25n_get_device_ident(struct w25n_softc * sc)170 w25n_get_device_ident(struct w25n_softc *sc)
171 {
172 	uint8_t txBuf[8], rxBuf[8];
173 	struct spi_command cmd;
174 	uint8_t manufacturer_id;
175 	uint16_t dev_id;
176 	int err, i;
177 
178 	memset(&cmd, 0, sizeof(cmd));
179 	memset(txBuf, 0, sizeof(txBuf));
180 	memset(rxBuf, 0, sizeof(rxBuf));
181 
182 	txBuf[0] = CMD_READ_IDENT;
183 	cmd.tx_cmd = &txBuf;
184 	cmd.rx_cmd = &rxBuf;
185 
186 	cmd.tx_cmd_sz = 5;
187 	cmd.rx_cmd_sz = 5;
188 	err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
189 	if (err)
190 		return (NULL);
191 
192 	manufacturer_id = rxBuf[2];
193 	dev_id = (rxBuf[3] << 8) | (rxBuf[4]);
194 
195 	for (i = 0; i < nitems(flash_devices); i++) {
196 		if ((flash_devices[i].manufacturer_id == manufacturer_id) &&
197 		    (flash_devices[i].device_id == dev_id))
198 			return &flash_devices[i];
199 	}
200 
201 	device_printf(sc->sc_dev,
202 	    "Unknown SPI NAND flash device. Vendor: %02x, device id: %04x\n",
203 	    manufacturer_id, dev_id);
204 	return (NULL);
205 }
206 
207 static int
w25n_write(struct w25n_softc * sc,off_t offset,caddr_t data,off_t count)208 w25n_write(struct w25n_softc *sc, off_t offset, caddr_t data, off_t count)
209 {
210 
211 	return (ENXIO);
212 
213 }
214 
215 static int
w25n_read(struct w25n_softc * sc,off_t offset,caddr_t data,off_t count)216 w25n_read(struct w25n_softc *sc, off_t offset, caddr_t data, off_t count)
217 {
218 	uint8_t txBuf[4], rxBuf[4];
219 	struct spi_command cmd;
220 	int err;
221 	int read_size;
222 	uint16_t page_idx;
223 	uint8_t st3, ecc_status;
224 
225 	/*
226 	 * We only support reading things at multiples of the page size.
227 	 */
228 	if (count % sc->sc_disk->d_sectorsize != 0) {
229 		device_printf(sc->sc_dev, "%s: invalid count\n", __func__);
230 		return (EIO);
231 	}
232 	if (offset % sc->sc_disk->d_sectorsize != 0) {
233 		device_printf(sc->sc_dev, "%s: invalid offset\n", __func__);
234 		return (EIO);
235 	}
236 
237 	page_idx = offset / sc->sc_disk->d_sectorsize;
238 
239 	while (count > 0) {
240 		/* Wait until we're ready */
241 		err = w25n_wait_for_device_ready(sc);
242 		if (err != 0) {
243 			device_printf(sc->sc_dev, "%s: failed to wait\n",
244 			    __func__);
245 			return (err);
246 		}
247 
248 		/* Issue the page change */
249 		err = w25n_set_page_address(sc, page_idx);
250 		if (err != 0) {
251 			device_printf(sc->sc_dev, "%s: page change failed\n",
252 			    __func__);
253 			return (err);
254 		}
255 
256 		/* Wait until the page change has read in data */
257 		err = w25n_wait_for_device_ready(sc);
258 		if (err != 0) {
259 			device_printf(sc->sc_dev,
260 			    "%s: failed to wait again\n",
261 			    __func__);
262 			return (err);
263 		}
264 
265 		/*
266 		 * Now we can issue a read command for the data
267 		 * in the buffer.  We'll read into the data buffer
268 		 * until we run out of data in this page.
269 		 *
270 		 * To simplify things we're not starting at an
271 		 * arbitrary offset; so the column address here
272 		 * inside the page is 0.  If we later want to support
273 		 * that kind of operation then we could do the math
274 		 * here.
275 		 */
276 		read_size = MIN(count, sc->sc_disk->d_sectorsize);
277 
278 		memset(data, 0xef, read_size);
279 
280 		txBuf[0] = CMD_FAST_READ;
281 		txBuf[1] = 0; /* column address 15:8 */
282 		txBuf[2] = 0; /* column address 7:0 */
283 		txBuf[3] = 0; /* dummy byte */
284 		cmd.tx_cmd_sz = 4;
285 		cmd.rx_cmd_sz = 4;
286 		cmd.tx_cmd = txBuf;
287 		cmd.rx_cmd = rxBuf;
288 
289 		cmd.tx_data = data;
290 		cmd.rx_data = data;
291 		cmd.tx_data_sz = read_size;
292 		cmd.rx_data_sz = read_size;
293 
294 		err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd);
295 		if (err != 0) {
296 			device_printf(sc->sc_dev,
297 			    "ERROR: failed to do FAST_READ (%u)\n",
298 			    err);
299 			return (err);
300 		}
301 
302 		/*
303 		 * Now, check ECC status bits, see if we had an ECC
304 		 * error.
305 		 */
306 		err = w25n_read_status_register(sc, STATUS_REG_3, &st3);
307 		if (err != 0) {
308 			device_printf(sc->sc_dev,
309 			    "%s: failed to wait again\n", __func__);
310 			return (err);
311 		}
312 		ecc_status = (st3 >> STATUS_REG_3_ECC_STATUS_SHIFT)
313 		    & STATUS_REG_3_ECC_STATUS_MASK;
314 		if ((ecc_status != STATUS_ECC_OK)
315 		    && (ecc_status != STATUS_ECC_1BIT_OK)) {
316 			device_printf(sc->sc_dev,
317 			    "%s: ECC status failed\n", __func__);
318 			return (EIO);
319 		}
320 
321 		count -= read_size;
322 		data += read_size;
323 		page_idx += 1;
324 	}
325 
326 	return (0);
327 }
328 
329 #ifdef	FDT
330 static struct ofw_compat_data compat_data[] = {
331 	{ "spi-nand",		1 },
332 	{ NULL,			0 },
333 };
334 #endif
335 
336 static int
w25n_probe(device_t dev)337 w25n_probe(device_t dev)
338 {
339 #ifdef FDT
340 	int i;
341 
342 	if (!ofw_bus_status_okay(dev))
343 		return (ENXIO);
344 
345 	/* First try to match the compatible property to the compat_data */
346 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 1)
347 		goto found;
348 
349 	/*
350 	 * Next, try to find a compatible device using the names in the
351 	 * flash_devices structure
352 	 */
353 	for (i = 0; i < nitems(flash_devices); i++)
354 		if (ofw_bus_is_compatible(dev, flash_devices[i].name))
355 			goto found;
356 
357 	return (ENXIO);
358 found:
359 #endif
360 	device_set_desc(dev, "W25N NAND Flash Family");
361 
362 	return (0);
363 }
364 
365 static int
w25n_attach(device_t dev)366 w25n_attach(device_t dev)
367 {
368 	struct w25n_softc *sc;
369 	struct w25n_flash_ident *ident;
370 	int err;
371 	uint8_t st1, st2, st3;
372 
373 	sc = device_get_softc(dev);
374 	sc->sc_dev = dev;
375 	sc->sc_parent = device_get_parent(sc->sc_dev);
376 
377 	W25N_LOCK_INIT(sc);
378 
379 	ident = w25n_get_device_ident(sc);
380 	if (ident == NULL)
381 		return (ENXIO);
382 
383 	if ((err = w25n_wait_for_device_ready(sc)) != 0)
384 		return (err);
385 
386 	/*
387 	 * Read the configuration, protection and status registers.
388 	 * Print them out here so the initial configuration can be checked.
389 	 */
390 	err = w25n_read_status_register(sc, STATUS_REG_1, &st1);
391 	if (err != 0)
392 		return (err);
393 	err = w25n_read_status_register(sc, STATUS_REG_2, &st2);
394 	if (err != 0)
395 		return (err);
396 	err = w25n_read_status_register(sc, STATUS_REG_3, &st3);
397 	if (err != 0)
398 		return (err);
399 
400 	device_printf(sc->sc_dev,
401 	    "device type %s, size %dK in %d sectors of %dK, erase size %dK\n",
402 	    ident->name,
403 	    ident->sectorcount * ident->sectorsize / 1024,
404 	    ident->sectorcount, ident->sectorsize / 1024,
405 	    ident->erasesize / 1024);
406 
407 	if (bootverbose)
408 		device_printf(sc->sc_dev,
409 		    "status1=0x%08x, status2=0x%08x, status3=0x%08x\n",
410 		    st1, st2, st3);
411 
412 	/*
413 	 * For now we're only going to support parts that have
414 	 * device ECC enabled.  Later on it may be interesting
415 	 * to do software driven ECC and figure out how we
416 	 * expose it over GEOM, but that day isn't today.
417 	 */
418 	if ((st2 & STATUS_REG_2_ECC_EN) == 0) {
419 		device_printf(sc->sc_dev,
420 		    "ERROR: only ECC in HW is supported\n");
421 		return (err);
422 	}
423 	if ((st2 & STATUS_REG_2_BUF_EN) == 0) {
424 		device_printf(sc->sc_dev,
425 		    "ERROR: only BUF mode is supported\n");
426 		return (err);
427 	}
428 
429 	sc->sc_flags = ident->flags;
430 	sc->sc_erasesize = ident->erasesize;
431 
432 	sc->sc_disk = disk_alloc();
433 	sc->sc_disk->d_open = w25n_open;
434 	sc->sc_disk->d_close = w25n_close;
435 	sc->sc_disk->d_strategy = w25n_strategy;
436 	sc->sc_disk->d_getattr = w25n_getattr;
437 	sc->sc_disk->d_ioctl = w25n_ioctl;
438 	sc->sc_disk->d_name = "nand_flash/spi";
439 	sc->sc_disk->d_drv1 = sc;
440 	sc->sc_disk->d_maxsize = DFLTPHYS;
441 	sc->sc_disk->d_sectorsize = ident->sectorsize;
442 	sc->sc_disk->d_mediasize = ident->sectorsize * ident->sectorcount;
443 	sc->sc_disk->d_stripesize = sc->sc_erasesize;
444 	sc->sc_disk->d_unit = device_get_unit(sc->sc_dev);
445 	sc->sc_disk->d_dump = NULL;		/* NB: no dumps */
446 	strlcpy(sc->sc_disk->d_descr, ident->name,
447 	    sizeof(sc->sc_disk->d_descr));
448 
449 	disk_create(sc->sc_disk, DISK_VERSION);
450 	bioq_init(&sc->sc_bio_queue);
451 	kproc_create(&w25n_task, sc, &sc->sc_p, 0, 0, "task: w25n flash");
452 	sc->sc_taskstate = TSTATE_RUNNING;
453 
454 	return (0);
455 }
456 
457 static int
w25n_detach(device_t dev)458 w25n_detach(device_t dev)
459 {
460 	struct w25n_softc *sc;
461 	int err;
462 
463 	sc = device_get_softc(dev);
464 	err = 0;
465 
466 	W25N_LOCK(sc);
467 	if (sc->sc_taskstate == TSTATE_RUNNING) {
468 		sc->sc_taskstate = TSTATE_STOPPING;
469 		wakeup(sc);
470 		while (err == 0 && sc->sc_taskstate != TSTATE_STOPPED) {
471 			err = msleep(sc, &sc->sc_mtx, 0, "w25nd", hz * 3);
472 			if (err != 0) {
473 				sc->sc_taskstate = TSTATE_RUNNING;
474 				device_printf(sc->sc_dev,
475 				    "Failed to stop queue task\n");
476 			}
477 		}
478 	}
479 	W25N_UNLOCK(sc);
480 
481 	if (err == 0 && sc->sc_taskstate == TSTATE_STOPPED) {
482 		disk_destroy(sc->sc_disk);
483 		bioq_flush(&sc->sc_bio_queue, NULL, ENXIO);
484 		W25N_LOCK_DESTROY(sc);
485 	}
486 	return (err);
487 }
488 
489 static int
w25n_open(struct disk * dp)490 w25n_open(struct disk *dp)
491 {
492 	return (0);
493 }
494 
495 static int
w25n_close(struct disk * dp)496 w25n_close(struct disk *dp)
497 {
498 
499 	return (0);
500 }
501 
502 static int
w25n_ioctl(struct disk * dp,u_long cmd,void * data,int fflag,struct thread * td)503 w25n_ioctl(struct disk *dp, u_long cmd, void *data, int fflag,
504 	struct thread *td)
505 {
506 
507 	return (EINVAL);
508 }
509 
510 static void
w25n_strategy(struct bio * bp)511 w25n_strategy(struct bio *bp)
512 {
513 	struct w25n_softc *sc;
514 
515 	sc = (struct w25n_softc *)bp->bio_disk->d_drv1;
516 	W25N_LOCK(sc);
517 	bioq_disksort(&sc->sc_bio_queue, bp);
518 	wakeup(sc);
519 	W25N_UNLOCK(sc);
520 }
521 
522 static int
w25n_getattr(struct bio * bp)523 w25n_getattr(struct bio *bp)
524 {
525 	struct w25n_softc *sc;
526 	device_t dev;
527 
528 	if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
529 		return (ENXIO);
530 
531 	sc = bp->bio_disk->d_drv1;
532 	dev = sc->sc_dev;
533 
534 	if (strcmp(bp->bio_attribute, "SPI::device") == 0) {
535 		if (bp->bio_length != sizeof(dev))
536 			return (EFAULT);
537 		bcopy(&dev, bp->bio_data, sizeof(dev));
538 	} else
539 		return (-1);
540 	return (0);
541 }
542 
543 static void
w25n_task(void * arg)544 w25n_task(void *arg)
545 {
546 	struct w25n_softc *sc = (struct w25n_softc*)arg;
547 	struct bio *bp;
548 
549 	for (;;) {
550 		W25N_LOCK(sc);
551 		do {
552 			if (sc->sc_taskstate == TSTATE_STOPPING) {
553 				sc->sc_taskstate = TSTATE_STOPPED;
554 				W25N_UNLOCK(sc);
555 				wakeup(sc);
556 				kproc_exit(0);
557 			}
558 			bp = bioq_first(&sc->sc_bio_queue);
559 			if (bp == NULL)
560 				msleep(sc, &sc->sc_mtx, PRIBIO, "w25nq", 0);
561 		} while (bp == NULL);
562 		bioq_remove(&sc->sc_bio_queue, bp);
563 		W25N_UNLOCK(sc);
564 
565 		switch (bp->bio_cmd) {
566 		case BIO_READ:
567 			bp->bio_error = w25n_read(sc, bp->bio_offset,
568 			    bp->bio_data, bp->bio_bcount);
569 			break;
570 		case BIO_WRITE:
571 			bp->bio_error = w25n_write(sc, bp->bio_offset,
572 			    bp->bio_data, bp->bio_bcount);
573 			break;
574 		default:
575 			bp->bio_error = EOPNOTSUPP;
576 		}
577 
578 
579 		biodone(bp);
580 	}
581 }
582 
583 static device_method_t w25n_methods[] = {
584 	/* Device interface */
585 	DEVMETHOD(device_probe,		w25n_probe),
586 	DEVMETHOD(device_attach,	w25n_attach),
587 	DEVMETHOD(device_detach,	w25n_detach),
588 
589 	{ 0, 0 }
590 };
591 
592 static driver_t w25n_driver = {
593 	"w25n",
594 	w25n_methods,
595 	sizeof(struct w25n_softc),
596 };
597 
598 DRIVER_MODULE(w25n, spibus, w25n_driver, 0, 0);
599 MODULE_DEPEND(w25n, spibus, 1, 1, 1);
600 #ifdef	FDT
601 MODULE_DEPEND(w25n, fdt_slicer, 1, 1, 1);
602 SPIBUS_FDT_PNP_INFO(compat_data);
603 #endif
604