nand_geom.c revision 330897
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (C) 2009-2012 Semihalf
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/11/sys/dev/nand/nand_geom.c 330897 2018-03-14 03:19:51Z eadler $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/conf.h>
35#include <sys/bus.h>
36#include <sys/malloc.h>
37#include <sys/uio.h>
38#include <sys/bio.h>
39#include <geom/geom.h>
40#include <geom/geom_disk.h>
41
42#include <dev/nand/nand.h>
43#include <dev/nand/nandbus.h>
44#include <dev/nand/nand_dev.h>
45#include "nand_if.h"
46#include "nandbus_if.h"
47
48#define	BIO_NAND_STD	((void *)1)
49#define	BIO_NAND_RAW	((void *)2)
50
51static disk_ioctl_t nand_ioctl;
52static disk_getattr_t nand_getattr;
53static disk_strategy_t nand_strategy;
54static disk_strategy_t nand_strategy_raw;
55
56static int
57nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
58{
59
60	nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip,
61	    offset);
62
63	return (nand_read_pages(chip, offset, buf, len));
64}
65
66static int
67nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
68{
69
70	nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip,
71	    offset);
72
73	return (nand_prog_pages(chip, offset, buf, len));
74}
75
76static int
77nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
78{
79	nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num,
80	    chip, offset);
81
82	return (nand_read_pages_raw(chip, offset, buf, len));
83}
84
85static int
86nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
87{
88
89	nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num,
90	    chip, offset);
91
92	return (nand_prog_pages_raw(chip, offset, buf, len));
93}
94
95static void
96nand_strategy(struct bio *bp)
97{
98	struct nand_chip *chip;
99
100	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
101
102	bp->bio_driver1 = BIO_NAND_STD;
103
104	nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
105	    bp->bio_cmd == BIO_READ ? "READ" :
106	    (bp->bio_cmd == BIO_WRITE ? "WRITE" :
107	    (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
108	    chip->num, chip);
109
110	mtx_lock(&chip->qlock);
111	bioq_insert_tail(&chip->bioq, bp);
112	mtx_unlock(&chip->qlock);
113	taskqueue_enqueue(chip->tq, &chip->iotask);
114}
115
116static void
117nand_strategy_raw(struct bio *bp)
118{
119	struct nand_chip *chip;
120
121	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
122
123	/* Inform taskqueue that it's a raw access */
124	bp->bio_driver1 = BIO_NAND_RAW;
125
126	nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
127	    bp->bio_cmd == BIO_READ ? "READ" :
128	    (bp->bio_cmd == BIO_WRITE ? "WRITE" :
129	    (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
130	    chip->num, chip);
131
132	mtx_lock(&chip->qlock);
133	bioq_insert_tail(&chip->bioq, bp);
134	mtx_unlock(&chip->qlock);
135	taskqueue_enqueue(chip->tq, &chip->iotask);
136}
137
138static int
139nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
140    uint32_t len, uint8_t *data, uint8_t write)
141{
142	struct chip_geom *cg;
143	int ret = 0;
144
145	cg = &chip->chip_geom;
146
147	if (!write)
148		ret = nand_read_oob(chip, page, data, cg->oob_size);
149	else
150		ret = nand_prog_oob(chip, page, data, cg->oob_size);
151
152	return (ret);
153}
154
155static int
156nand_getattr(struct bio *bp)
157{
158	struct nand_chip *chip;
159	struct chip_geom *cg;
160	device_t dev;
161	int val;
162
163	if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
164		return (ENXIO);
165
166	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
167	cg = &(chip->chip_geom);
168
169	dev = device_get_parent(chip->dev);
170	dev = device_get_parent(dev);
171
172	if (strcmp(bp->bio_attribute, "NAND::device") == 0) {
173		if (bp->bio_length != sizeof(dev))
174			return (EFAULT);
175		bcopy(&dev, bp->bio_data, sizeof(dev));
176	} else {
177		if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0)
178			val = cg->oob_size;
179		else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0)
180			val = cg->page_size;
181		else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0)
182			val = cg->block_size;
183		else
184			return (-1);
185		if (bp->bio_length != sizeof(val))
186			return (EFAULT);
187		bcopy(&val, bp->bio_data, sizeof(val));
188	}
189	bp->bio_completed = bp->bio_length;
190	return (0);
191}
192
193static int
194nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag,
195    struct thread *td)
196{
197	struct nand_chip *chip;
198	struct chip_geom  *cg;
199	struct nand_oob_rw *oob_rw = NULL;
200	struct nand_raw_rw *raw_rw = NULL;
201	device_t nandbus;
202	size_t bufsize = 0, len = 0;
203	size_t raw_size;
204	off_t off;
205	uint8_t *buf = NULL;
206	int ret = 0;
207	uint8_t status;
208
209	chip = (struct nand_chip *)ndisk->d_drv1;
210	cg = &chip->chip_geom;
211	nandbus = device_get_parent(chip->dev);
212
213	if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
214		raw_rw = (struct nand_raw_rw *)data;
215		raw_size =  cg->pgs_per_blk * (cg->page_size + cg->oob_size);
216
217		/* Check if len is not bigger than chip size */
218		if (raw_rw->len > raw_size)
219			return (EFBIG);
220
221		/*
222		 * Do not ask for too much memory, in case of large transfers
223		 * read/write in 16-pages chunks
224		 */
225		bufsize = 16 * (cg->page_size + cg->oob_size);
226		if (raw_rw->len < bufsize)
227			bufsize = raw_rw->len;
228
229		buf = malloc(bufsize, M_NAND, M_WAITOK);
230		len = raw_rw->len;
231		off = 0;
232	}
233
234	switch (cmd) {
235	case NAND_IO_ERASE:
236		ret = nand_erase_blocks(chip, ((off_t *)data)[0],
237		    ((off_t *)data)[1]);
238		break;
239
240	case NAND_IO_OOB_READ:
241		oob_rw = (struct nand_oob_rw *)data;
242		ret = nand_oob_access(chip, oob_rw->page, 0,
243		    oob_rw->len, oob_rw->data, 0);
244		break;
245
246	case NAND_IO_OOB_PROG:
247		oob_rw = (struct nand_oob_rw *)data;
248		ret = nand_oob_access(chip, oob_rw->page, 0,
249		    oob_rw->len, oob_rw->data, 1);
250		break;
251
252	case NAND_IO_GET_STATUS:
253		NANDBUS_LOCK(nandbus);
254		ret = NANDBUS_GET_STATUS(nandbus, &status);
255		if (ret == 0)
256			*(uint8_t *)data = status;
257		NANDBUS_UNLOCK(nandbus);
258		break;
259
260	case NAND_IO_RAW_PROG:
261		while (len > 0) {
262			if (len < bufsize)
263				bufsize = len;
264
265			ret = copyin(raw_rw->data + off, buf, bufsize);
266			if (ret)
267				break;
268			ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
269			    bufsize);
270			if (ret)
271				break;
272			len -= bufsize;
273			off += bufsize;
274		}
275		break;
276
277	case NAND_IO_RAW_READ:
278		while (len > 0) {
279			if (len < bufsize)
280				bufsize = len;
281
282			ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
283			    bufsize);
284			if (ret)
285				break;
286
287			ret = copyout(buf, raw_rw->data + off, bufsize);
288			if (ret)
289				break;
290			len -= bufsize;
291			off += bufsize;
292		}
293		break;
294
295	case NAND_IO_GET_CHIP_PARAM:
296		nand_get_chip_param(chip, (struct chip_param_io *)data);
297		break;
298
299	default:
300		printf("Unknown nand_ioctl request \n");
301		ret = EIO;
302	}
303
304	if (buf)
305		free(buf, M_NAND);
306
307	return (ret);
308}
309
310static void
311nand_io_proc(void *arg, int pending)
312{
313	struct nand_chip *chip = arg;
314	struct bio *bp;
315	int err = 0;
316
317	for (;;) {
318		mtx_lock(&chip->qlock);
319		bp = bioq_takefirst(&chip->bioq);
320		mtx_unlock(&chip->qlock);
321		if (bp == NULL)
322			break;
323
324		if (bp->bio_driver1 == BIO_NAND_STD) {
325			if (bp->bio_cmd == BIO_READ) {
326				err = nand_read(chip,
327				    bp->bio_offset & 0xffffffff,
328				    bp->bio_data, bp->bio_bcount);
329			} else if (bp->bio_cmd == BIO_WRITE) {
330				err = nand_write(chip,
331				    bp->bio_offset & 0xffffffff,
332				    bp->bio_data, bp->bio_bcount);
333			}
334		} else if (bp->bio_driver1 == BIO_NAND_RAW) {
335			if (bp->bio_cmd == BIO_READ) {
336				err = nand_read_raw(chip,
337				    bp->bio_offset & 0xffffffff,
338				    bp->bio_data, bp->bio_bcount);
339			} else if (bp->bio_cmd == BIO_WRITE) {
340				err = nand_write_raw(chip,
341				    bp->bio_offset & 0xffffffff,
342				    bp->bio_data, bp->bio_bcount);
343			}
344		} else
345			panic("Unknown access type in bio->bio_driver1\n");
346
347		if (bp->bio_cmd == BIO_DELETE) {
348			nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld "
349			    "length %ld\n", chip->num, bp->bio_offset,
350			    bp->bio_bcount);
351			err = nand_erase_blocks(chip,
352			    bp->bio_offset & 0xffffffff,
353			    bp->bio_bcount);
354		}
355
356		if (err == 0 || err == ECC_CORRECTABLE)
357			bp->bio_resid = 0;
358		else {
359			nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] "
360			    "error: %d\n", err);
361
362			bp->bio_error = EIO;
363			bp->bio_flags |= BIO_ERROR;
364			bp->bio_resid = bp->bio_bcount;
365		}
366		biodone(bp);
367	}
368}
369
370int
371create_geom_disk(struct nand_chip *chip)
372{
373	struct disk *ndisk, *rdisk;
374
375	/* Create the disk device */
376	ndisk = disk_alloc();
377	ndisk->d_strategy = nand_strategy;
378	ndisk->d_ioctl = nand_ioctl;
379	ndisk->d_getattr = nand_getattr;
380	ndisk->d_name = "gnand";
381	ndisk->d_drv1 = chip;
382	ndisk->d_maxsize = chip->chip_geom.block_size;
383	ndisk->d_sectorsize = chip->chip_geom.page_size;
384	ndisk->d_mediasize = chip->chip_geom.chip_size;
385	ndisk->d_unit = chip->num +
386	    10 * device_get_unit(device_get_parent(chip->dev));
387
388	/*
389	 * When using BBT, make two last blocks of device unavailable
390	 * to user (because those are used to store BBT table).
391	 */
392	if (chip->bbt != NULL)
393		ndisk->d_mediasize -= (2 * chip->chip_geom.block_size);
394
395	ndisk->d_flags = DISKFLAG_CANDELETE;
396
397	snprintf(ndisk->d_ident, sizeof(ndisk->d_ident),
398	    "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
399	ndisk->d_rotation_rate = DISK_RR_NON_ROTATING;
400
401	disk_create(ndisk, DISK_VERSION);
402
403	/* Create the RAW disk device */
404	rdisk = disk_alloc();
405	rdisk->d_strategy = nand_strategy_raw;
406	rdisk->d_ioctl = nand_ioctl;
407	rdisk->d_getattr = nand_getattr;
408	rdisk->d_name = "gnand.raw";
409	rdisk->d_drv1 = chip;
410	rdisk->d_maxsize = chip->chip_geom.block_size;
411	rdisk->d_sectorsize = chip->chip_geom.page_size;
412	rdisk->d_mediasize = chip->chip_geom.chip_size;
413	rdisk->d_unit = chip->num +
414	    10 * device_get_unit(device_get_parent(chip->dev));
415
416	rdisk->d_flags = DISKFLAG_CANDELETE;
417
418	snprintf(rdisk->d_ident, sizeof(rdisk->d_ident),
419	    "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id,
420	    chip->id.dev_id);
421	rdisk->d_rotation_rate = DISK_RR_NON_ROTATING;
422
423	disk_create(rdisk, DISK_VERSION);
424
425	chip->ndisk = ndisk;
426	chip->rdisk = rdisk;
427
428	mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF);
429	bioq_init(&chip->bioq);
430
431	TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
432	chip->tq = taskqueue_create("nand_taskq", M_WAITOK,
433	    taskqueue_thread_enqueue, &chip->tq);
434	taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq");
435
436	if (bootverbose)
437		device_printf(chip->dev, "Created gnand%d for chip [0x%0x, "
438		    "0x%0x]\n", ndisk->d_unit, chip->id.man_id,
439		    chip->id.dev_id);
440
441	return (0);
442}
443
444void
445destroy_geom_disk(struct nand_chip *chip)
446{
447	struct bio *bp;
448
449	taskqueue_free(chip->tq);
450	disk_destroy(chip->ndisk);
451	disk_destroy(chip->rdisk);
452
453	mtx_lock(&chip->qlock);
454	for (;;) {
455		bp = bioq_takefirst(&chip->bioq);
456		if (bp == NULL)
457			break;
458		bp->bio_error = EIO;
459		bp->bio_flags |= BIO_ERROR;
460		bp->bio_resid = bp->bio_bcount;
461
462		biodone(bp);
463	}
464	mtx_unlock(&chip->qlock);
465
466	mtx_destroy(&chip->qlock);
467}
468