xref: /freebsd-11-stable/sys/dev/nand/nand_cdev.c (revision c228a85b162b66704826886c299c2d841ab33fb2)
1 /*-
2  * Copyright (C) 2009-2012 Semihalf
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/conf.h>
33 #include <sys/bus.h>
34 #include <sys/malloc.h>
35 #include <sys/uio.h>
36 #include <sys/bio.h>
37 
38 #include <dev/nand/nand.h>
39 #include <dev/nand/nandbus.h>
40 #include <dev/nand/nand_dev.h>
41 #include "nand_if.h"
42 #include "nandbus_if.h"
43 
44 static int nand_page_stat(struct nand_chip *, struct page_stat_io *);
45 static int nand_block_stat(struct nand_chip *, struct block_stat_io *);
46 
47 static d_ioctl_t nand_ioctl;
48 static d_open_t nand_open;
49 static d_strategy_t nand_strategy;
50 
51 static struct cdevsw nand_cdevsw = {
52 	.d_version	= D_VERSION,
53 	.d_name		= "nand",
54 	.d_open		= nand_open,
55 	.d_read		= physread,
56 	.d_write	= physwrite,
57 	.d_ioctl	= nand_ioctl,
58 	.d_strategy =	nand_strategy,
59 };
60 
61 static int
offset_to_page(struct chip_geom * cg,uint32_t offset)62 offset_to_page(struct chip_geom *cg, uint32_t offset)
63 {
64 
65 	return (offset / cg->page_size);
66 }
67 
68 static int
offset_to_page_off(struct chip_geom * cg,uint32_t offset)69 offset_to_page_off(struct chip_geom *cg, uint32_t offset)
70 {
71 
72 	return (offset % cg->page_size);
73 }
74 
75 int
nand_make_dev(struct nand_chip * chip)76 nand_make_dev(struct nand_chip *chip)
77 {
78 	struct nandbus_ivar *ivar;
79 	device_t parent, nandbus;
80 	int parent_unit, unit;
81 	char *name;
82 
83 	ivar = device_get_ivars(chip->dev);
84 	nandbus = device_get_parent(chip->dev);
85 
86 	if (ivar->chip_cdev_name) {
87 		name = ivar->chip_cdev_name;
88 
89 		/*
90 		 * If we got distinct name for chip device we can enumarete it
91 		 * based on contoller number.
92 		 */
93 		parent = device_get_parent(nandbus);
94 	} else {
95 		name = "nand";
96 		parent = nandbus;
97 	}
98 
99 	parent_unit = device_get_unit(parent);
100 	unit = parent_unit * 4 + chip->num;
101 	chip->cdev = make_dev(&nand_cdevsw, unit, UID_ROOT, GID_WHEEL,
102 	    0640, "%s%d.%d", name, parent_unit, chip->num);
103 
104 	if (chip->cdev == NULL)
105 		return (ENXIO);
106 
107 	if (bootverbose)
108 		device_printf(chip->dev, "Created cdev %s%d.%d for chip "
109 		    "[0x%0x, 0x%0x]\n", name, parent_unit, chip->num,
110 		    ivar->man_id, ivar->dev_id);
111 
112 	chip->cdev->si_drv1 = chip;
113 
114 	return (0);
115 }
116 
117 void
nand_destroy_dev(struct nand_chip * chip)118 nand_destroy_dev(struct nand_chip *chip)
119 {
120 
121 	if (chip->cdev)
122 		destroy_dev(chip->cdev);
123 }
124 
125 static int
nand_open(struct cdev * dev,int oflags,int devtype,struct thread * td)126 nand_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
127 {
128 
129 	return (0);
130 }
131 
132 static int
nand_read(struct nand_chip * chip,uint32_t offset,void * buf,uint32_t len)133 nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
134 {
135 	struct chip_geom *cg;
136 	device_t nandbus;
137 	int start_page, count, off, err = 0;
138 	uint8_t *ptr, *tmp;
139 
140 	nand_debug(NDBG_CDEV, "Read from chip%d [%p] at %d\n", chip->num,
141 	    chip, offset);
142 
143 	nandbus = device_get_parent(chip->dev);
144 	NANDBUS_LOCK(nandbus);
145 	NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
146 
147 	cg = &chip->chip_geom;
148 	start_page = offset_to_page(cg, offset);
149 	off = offset_to_page_off(cg, offset);
150 	count = (len > cg->page_size - off) ? cg->page_size - off : len;
151 
152 	ptr = (uint8_t *)buf;
153 	while (len > 0) {
154 		if (len < cg->page_size) {
155 			tmp = malloc(cg->page_size, M_NAND, M_WAITOK);
156 			if (!tmp) {
157 				err = ENOMEM;
158 				break;
159 			}
160 			err = NAND_READ_PAGE(chip->dev, start_page,
161 			    tmp, cg->page_size, 0);
162 			if (err) {
163 				free(tmp, M_NAND);
164 				break;
165 			}
166 			bcopy(tmp + off, ptr, count);
167 			free(tmp, M_NAND);
168 		} else {
169 			err = NAND_READ_PAGE(chip->dev, start_page,
170 			    ptr, cg->page_size, 0);
171 			if (err)
172 				break;
173 		}
174 
175 		len -= count;
176 		start_page++;
177 		ptr += count;
178 		count = (len > cg->page_size) ? cg->page_size : len;
179 		off = 0;
180 	}
181 
182 	NANDBUS_UNLOCK(nandbus);
183 	return (err);
184 }
185 
186 static int
nand_write(struct nand_chip * chip,uint32_t offset,void * buf,uint32_t len)187 nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
188 {
189 	struct chip_geom *cg;
190 	device_t nandbus;
191 	int off, start_page, err = 0;
192 	uint8_t *ptr;
193 
194 	nand_debug(NDBG_CDEV, "Write to chip %d [%p] at %d\n", chip->num,
195 	    chip, offset);
196 
197 	nandbus = device_get_parent(chip->dev);
198 	NANDBUS_LOCK(nandbus);
199 	NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
200 
201 	cg = &chip->chip_geom;
202 	start_page = offset_to_page(cg, offset);
203 	off = offset_to_page_off(cg, offset);
204 
205 	if (off != 0 || (len % cg->page_size) != 0) {
206 		printf("Not aligned write start [0x%08x] size [0x%08x]\n",
207 		    off, len);
208 		NANDBUS_UNLOCK(nandbus);
209 		return (EINVAL);
210 	}
211 
212 	ptr = (uint8_t *)buf;
213 	while (len > 0) {
214 		err = NAND_PROGRAM_PAGE(chip->dev, start_page, ptr,
215 		    cg->page_size, 0);
216 		if (err)
217 			break;
218 
219 		len -= cg->page_size;
220 		start_page++;
221 		ptr += cg->page_size;
222 	}
223 
224 	NANDBUS_UNLOCK(nandbus);
225 	return (err);
226 }
227 
228 static void
nand_strategy(struct bio * bp)229 nand_strategy(struct bio *bp)
230 {
231 	struct nand_chip *chip;
232 	struct cdev *dev;
233 	int err = 0;
234 
235 	dev = bp->bio_dev;
236 	chip = dev->si_drv1;
237 
238 	nand_debug(NDBG_CDEV, "Strategy %s on chip %d [%p]\n",
239 	    bp->bio_cmd == BIO_READ ? "READ" : "WRITE",
240 	    chip->num, chip);
241 
242 	if (bp->bio_cmd == BIO_READ) {
243 		err = nand_read(chip,
244 		    bp->bio_offset & 0xffffffff,
245 		    bp->bio_data, bp->bio_bcount);
246 	} else {
247 		err = nand_write(chip,
248 		    bp->bio_offset & 0xffffffff,
249 		    bp->bio_data, bp->bio_bcount);
250 	}
251 
252 	if (err == 0)
253 		bp->bio_resid = 0;
254 	else {
255 		bp->bio_error = EIO;
256 		bp->bio_flags |= BIO_ERROR;
257 		bp->bio_resid = bp->bio_bcount;
258 	}
259 
260 	biodone(bp);
261 }
262 
263 static int
nand_oob_access(struct nand_chip * chip,uint32_t page,uint32_t offset,uint32_t len,uint8_t * data,uint8_t write)264 nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
265     uint32_t len, uint8_t *data, uint8_t write)
266 {
267 	struct chip_geom *cg;
268 	uint8_t *buf = NULL;
269 	int ret = 0;
270 
271 	cg = &chip->chip_geom;
272 
273 	buf = malloc(cg->oob_size, M_NAND, M_WAITOK);
274 	if (!buf)
275 		return (ENOMEM);
276 
277 	memset(buf, 0xff, cg->oob_size);
278 
279 	if (!write) {
280 		ret = nand_read_oob(chip, page, buf, cg->oob_size);
281 		copyout(buf, data, len);
282 	} else {
283 		copyin(data, buf, len);
284 		ret = nand_prog_oob(chip, page, buf, cg->oob_size);
285 	}
286 
287 	free(buf, M_NAND);
288 
289 	return (ret);
290 }
291 
292 static int
nand_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int fflag,struct thread * td)293 nand_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
294     struct thread *td)
295 {
296 	struct nand_chip *chip;
297 	struct chip_geom  *cg;
298 	struct nand_oob_rw *oob_rw = NULL;
299 	struct nand_raw_rw *raw_rw = NULL;
300 	device_t nandbus;
301 	size_t bufsize = 0, len = 0;
302 	size_t raw_size;
303 	off_t off;
304 	uint8_t *buf = NULL;
305 	int ret = 0;
306 	uint8_t status;
307 
308 	chip = (struct nand_chip *)dev->si_drv1;
309 	cg = &chip->chip_geom;
310 	nandbus = device_get_parent(chip->dev);
311 
312 	if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
313 		raw_rw = (struct nand_raw_rw *)data;
314 		raw_size =  cg->pgs_per_blk * (cg->page_size + cg->oob_size);
315 
316 		/* Check if len is not bigger than chip size */
317 		if (raw_rw->len > raw_size)
318 			return (EFBIG);
319 
320 		/*
321 		 * Do not ask for too much memory, in case of large transfers
322 		 * read/write in 16-pages chunks
323 		 */
324 		bufsize = 16 * (cg->page_size + cg->oob_size);
325 		if (raw_rw->len < bufsize)
326 			bufsize = raw_rw->len;
327 
328 		buf = malloc(bufsize, M_NAND, M_WAITOK);
329 		len = raw_rw->len;
330 		off = 0;
331 	}
332 	switch(cmd) {
333 	case NAND_IO_ERASE:
334 		ret = nand_erase_blocks(chip, ((off_t *)data)[0],
335 		    ((off_t *)data)[1]);
336 		break;
337 
338 	case NAND_IO_OOB_READ:
339 		oob_rw = (struct nand_oob_rw *)data;
340 		ret = nand_oob_access(chip, oob_rw->page, 0,
341 		    oob_rw->len, oob_rw->data, 0);
342 		break;
343 
344 	case NAND_IO_OOB_PROG:
345 		oob_rw = (struct nand_oob_rw *)data;
346 		ret = nand_oob_access(chip, oob_rw->page, 0,
347 		    oob_rw->len, oob_rw->data, 1);
348 		break;
349 
350 	case NAND_IO_GET_STATUS:
351 		NANDBUS_LOCK(nandbus);
352 		ret = NANDBUS_GET_STATUS(nandbus, &status);
353 		if (ret == 0)
354 			*(uint8_t *)data = status;
355 		NANDBUS_UNLOCK(nandbus);
356 		break;
357 
358 	case NAND_IO_RAW_PROG:
359 		while (len > 0) {
360 			if (len < bufsize)
361 				bufsize = len;
362 			ret = copyin(raw_rw->data + off, buf, bufsize);
363 			if (ret)
364 				break;
365 			ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
366 			    bufsize);
367 			if (ret)
368 				break;
369 			len -= bufsize;
370 			off += bufsize;
371 		}
372 		break;
373 
374 	case NAND_IO_RAW_READ:
375 		while (len > 0) {
376 			if (len < bufsize)
377 				bufsize = len;
378 
379 			ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
380 			    bufsize);
381 			if (ret)
382 				break;
383 
384 			ret = copyout(buf, raw_rw->data + off, bufsize);
385 			if (ret)
386 				break;
387 			len -= bufsize;
388 			off += bufsize;
389 		}
390 		break;
391 
392 	case NAND_IO_PAGE_STAT:
393 		ret = nand_page_stat(chip, (struct page_stat_io *)data);
394 		break;
395 
396 	case NAND_IO_BLOCK_STAT:
397 		ret = nand_block_stat(chip, (struct block_stat_io *)data);
398 		break;
399 
400 	case NAND_IO_GET_CHIP_PARAM:
401 		nand_get_chip_param(chip, (struct chip_param_io *)data);
402 		break;
403 
404 	default:
405 		printf("Unknown nand_ioctl request \n");
406 		ret = EIO;
407 	}
408 
409 	if (buf)
410 		free(buf, M_NAND);
411 
412 	return (ret);
413 }
414 
415 static int
nand_page_stat(struct nand_chip * chip,struct page_stat_io * page_stat)416 nand_page_stat(struct nand_chip *chip, struct page_stat_io *page_stat)
417 {
418 	struct chip_geom *cg;
419 	struct page_stat *stat;
420 	int num_pages;
421 
422 	cg = &chip->chip_geom;
423 	num_pages = cg->pgs_per_blk * cg->blks_per_lun * cg->luns;
424 	if (page_stat->page_num >= num_pages)
425 		return (EINVAL);
426 
427 	stat = &chip->pg_stat[page_stat->page_num];
428 	page_stat->page_read = stat->page_read;
429 	page_stat->page_written = stat->page_written;
430 	page_stat->page_raw_read = stat->page_raw_read;
431 	page_stat->page_raw_written = stat->page_raw_written;
432 	page_stat->ecc_succeded = stat->ecc_stat.ecc_succeded;
433 	page_stat->ecc_corrected = stat->ecc_stat.ecc_corrected;
434 	page_stat->ecc_failed = stat->ecc_stat.ecc_failed;
435 
436 	return (0);
437 }
438 
439 static int
nand_block_stat(struct nand_chip * chip,struct block_stat_io * block_stat)440 nand_block_stat(struct nand_chip *chip, struct block_stat_io *block_stat)
441 {
442 	struct chip_geom *cg;
443 	uint32_t block_num = block_stat->block_num;
444 
445 	cg = &chip->chip_geom;
446 	if (block_num >= cg->blks_per_lun * cg->luns)
447 		return (EINVAL);
448 
449 	block_stat->block_erased = chip->blk_stat[block_num].block_erased;
450 
451 	return (0);
452 }
453