Lines Matching +full:x +full:- +full:ecc
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
88 #define W25N_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
89 #define W25N_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
91 mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
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);
128 err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd); in w25n_read_status_register()
163 err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd); in w25n_set_page_address()
188 err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd); in w25n_get_device_ident()
201 device_printf(sc->sc_dev, in w25n_get_device_ident()
202 "Unknown SPI NAND flash device. Vendor: %02x, device id: %04x\n", in w25n_get_device_ident()
228 if (count % sc->sc_disk->d_sectorsize != 0) { in w25n_read()
229 device_printf(sc->sc_dev, "%s: invalid count\n", __func__); in w25n_read()
232 if (offset % sc->sc_disk->d_sectorsize != 0) { in w25n_read()
233 device_printf(sc->sc_dev, "%s: invalid offset\n", __func__); in w25n_read()
237 page_idx = offset / sc->sc_disk->d_sectorsize; in w25n_read()
243 device_printf(sc->sc_dev, "%s: failed to wait\n", in w25n_read()
251 device_printf(sc->sc_dev, "%s: page change failed\n", in w25n_read()
259 device_printf(sc->sc_dev, in w25n_read()
276 read_size = MIN(count, sc->sc_disk->d_sectorsize); in w25n_read()
294 err = SPIBUS_TRANSFER(sc->sc_parent, sc->sc_dev, &cmd); in w25n_read()
296 device_printf(sc->sc_dev, in w25n_read()
303 * Now, check ECC status bits, see if we had an ECC in w25n_read()
308 device_printf(sc->sc_dev, in w25n_read()
316 device_printf(sc->sc_dev, in w25n_read()
317 "%s: ECC status failed\n", __func__); in w25n_read()
321 count -= read_size; in w25n_read()
331 { "spi-nand", 1 },
346 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 1) in w25n_probe()
374 sc->sc_dev = dev; in w25n_attach()
375 sc->sc_parent = device_get_parent(sc->sc_dev); in w25n_attach()
400 device_printf(sc->sc_dev, in w25n_attach()
402 ident->name, in w25n_attach()
403 ident->sectorcount * ident->sectorsize / 1024, in w25n_attach()
404 ident->sectorcount, ident->sectorsize / 1024, in w25n_attach()
405 ident->erasesize / 1024); in w25n_attach()
408 device_printf(sc->sc_dev, in w25n_attach()
409 "status1=0x%08x, status2=0x%08x, status3=0x%08x\n", in w25n_attach()
414 * device ECC enabled. Later on it may be interesting in w25n_attach()
415 * to do software driven ECC and figure out how we in w25n_attach()
419 device_printf(sc->sc_dev, in w25n_attach()
420 "ERROR: only ECC in HW is supported\n"); in w25n_attach()
424 device_printf(sc->sc_dev, in w25n_attach()
429 sc->sc_flags = ident->flags; in w25n_attach()
430 sc->sc_erasesize = ident->erasesize; in w25n_attach()
432 sc->sc_disk = disk_alloc(); in w25n_attach()
433 sc->sc_disk->d_open = w25n_open; in w25n_attach()
434 sc->sc_disk->d_close = w25n_close; in w25n_attach()
435 sc->sc_disk->d_strategy = w25n_strategy; in w25n_attach()
436 sc->sc_disk->d_getattr = w25n_getattr; in w25n_attach()
437 sc->sc_disk->d_ioctl = w25n_ioctl; in w25n_attach()
438 sc->sc_disk->d_name = "nand_flash/spi"; in w25n_attach()
439 sc->sc_disk->d_drv1 = sc; in w25n_attach()
440 sc->sc_disk->d_maxsize = DFLTPHYS; in w25n_attach()
441 sc->sc_disk->d_sectorsize = ident->sectorsize; in w25n_attach()
442 sc->sc_disk->d_mediasize = ident->sectorsize * ident->sectorcount; in w25n_attach()
443 sc->sc_disk->d_stripesize = sc->sc_erasesize; in w25n_attach()
444 sc->sc_disk->d_unit = device_get_unit(sc->sc_dev); in w25n_attach()
445 sc->sc_disk->d_dump = NULL; /* NB: no dumps */ in w25n_attach()
446 strlcpy(sc->sc_disk->d_descr, ident->name, in w25n_attach()
447 sizeof(sc->sc_disk->d_descr)); in w25n_attach()
449 disk_create(sc->sc_disk, DISK_VERSION); in w25n_attach()
450 bioq_init(&sc->sc_bio_queue); in w25n_attach()
451 kproc_create(&w25n_task, sc, &sc->sc_p, 0, 0, "task: w25n flash"); in w25n_attach()
452 sc->sc_taskstate = TSTATE_RUNNING; in w25n_attach()
467 if (sc->sc_taskstate == TSTATE_RUNNING) { in w25n_detach()
468 sc->sc_taskstate = TSTATE_STOPPING; in w25n_detach()
470 while (err == 0 && sc->sc_taskstate != TSTATE_STOPPED) { in w25n_detach()
471 err = msleep(sc, &sc->sc_mtx, 0, "w25nd", hz * 3); in w25n_detach()
473 sc->sc_taskstate = TSTATE_RUNNING; in w25n_detach()
474 device_printf(sc->sc_dev, in w25n_detach()
481 if (err == 0 && sc->sc_taskstate == TSTATE_STOPPED) { in w25n_detach()
482 disk_destroy(sc->sc_disk); in w25n_detach()
483 bioq_flush(&sc->sc_bio_queue, NULL, ENXIO); in w25n_detach()
515 sc = (struct w25n_softc *)bp->bio_disk->d_drv1; in w25n_strategy()
517 bioq_disksort(&sc->sc_bio_queue, bp); in w25n_strategy()
528 if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL) in w25n_getattr()
531 sc = bp->bio_disk->d_drv1; in w25n_getattr()
532 dev = sc->sc_dev; in w25n_getattr()
534 if (strcmp(bp->bio_attribute, "SPI::device") == 0) { in w25n_getattr()
535 if (bp->bio_length != sizeof(dev)) in w25n_getattr()
537 bcopy(&dev, bp->bio_data, sizeof(dev)); in w25n_getattr()
539 return (-1); in w25n_getattr()
552 if (sc->sc_taskstate == TSTATE_STOPPING) { in w25n_task()
553 sc->sc_taskstate = TSTATE_STOPPED; in w25n_task()
558 bp = bioq_first(&sc->sc_bio_queue); in w25n_task()
560 msleep(sc, &sc->sc_mtx, PRIBIO, "w25nq", 0); in w25n_task()
562 bioq_remove(&sc->sc_bio_queue, bp); in w25n_task()
565 switch (bp->bio_cmd) { in w25n_task()
567 bp->bio_error = w25n_read(sc, bp->bio_offset, in w25n_task()
568 bp->bio_data, bp->bio_bcount); in w25n_task()
571 bp->bio_error = w25n_write(sc, bp->bio_offset, in w25n_task()
572 bp->bio_data, bp->bio_bcount); in w25n_task()
575 bp->bio_error = EOPNOTSUPP; in w25n_task()