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