]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/nand/nand_geom.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / nand / nand_geom.c
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 #include <geom/geom.h>
38 #include <geom/geom_disk.h>
39
40 #include <dev/nand/nand.h>
41 #include <dev/nand/nandbus.h>
42 #include <dev/nand/nand_dev.h>
43 #include "nand_if.h"
44 #include "nandbus_if.h"
45
46 #define BIO_NAND_STD    ((void *)1)
47 #define BIO_NAND_RAW    ((void *)2)
48
49 static disk_ioctl_t nand_ioctl;
50 static disk_getattr_t nand_getattr;
51 static disk_strategy_t nand_strategy;
52 static disk_strategy_t nand_strategy_raw;
53
54 static int
55 nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
56 {
57
58         nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip,
59             offset);
60
61         return (nand_read_pages(chip, offset, buf, len));
62 }
63
64 static int
65 nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
66 {
67
68         nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip,
69             offset);
70
71         return (nand_prog_pages(chip, offset, buf, len));
72 }
73
74 static int
75 nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
76 {
77         nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num,
78             chip, offset);
79
80         return (nand_read_pages_raw(chip, offset, buf, len));
81 }
82
83 static int
84 nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
85 {
86
87         nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num,
88             chip, offset);
89
90         return (nand_prog_pages_raw(chip, offset, buf, len));
91 }
92
93 static void
94 nand_strategy(struct bio *bp)
95 {
96         struct nand_chip *chip;
97
98         chip = (struct nand_chip *)bp->bio_disk->d_drv1;
99
100         bp->bio_driver1 = BIO_NAND_STD;
101
102         nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
103             (bp->bio_cmd & BIO_READ) == BIO_READ ? "READ" :
104             ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE ? "WRITE" :
105             ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE ? "DELETE" : "UNKNOWN")),
106             chip->num, chip);
107
108         mtx_lock(&chip->qlock);
109         bioq_insert_tail(&chip->bioq, bp);
110         mtx_unlock(&chip->qlock);
111         taskqueue_enqueue(chip->tq, &chip->iotask);
112 }
113
114 static void
115 nand_strategy_raw(struct bio *bp)
116 {
117         struct nand_chip *chip;
118
119         chip = (struct nand_chip *)bp->bio_disk->d_drv1;
120
121         /* Inform taskqueue that it's a raw access */
122         bp->bio_driver1 = BIO_NAND_RAW;
123
124         nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
125             (bp->bio_cmd & BIO_READ) == BIO_READ ? "READ" :
126             ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE ? "WRITE" :
127             ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE ? "DELETE" : "UNKNOWN")),
128             chip->num, chip);
129
130         mtx_lock(&chip->qlock);
131         bioq_insert_tail(&chip->bioq, bp);
132         mtx_unlock(&chip->qlock);
133         taskqueue_enqueue(chip->tq, &chip->iotask);
134 }
135
136 static int
137 nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
138     uint32_t len, uint8_t *data, uint8_t write)
139 {
140         struct chip_geom *cg;
141         int ret = 0;
142
143         cg = &chip->chip_geom;
144
145         if (!write)
146                 ret = nand_read_oob(chip, page, data, cg->oob_size);
147         else
148                 ret = nand_prog_oob(chip, page, data, cg->oob_size);
149
150         return (ret);
151 }
152
153 static int
154 nand_getattr(struct bio *bp)
155 {
156         struct nand_chip *chip;
157         struct chip_geom *cg;
158         device_t dev;
159         int val;
160
161         if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
162                 return (ENXIO);
163
164         chip = (struct nand_chip *)bp->bio_disk->d_drv1;
165         cg = &(chip->chip_geom);
166
167         dev = device_get_parent(chip->dev);
168         dev = device_get_parent(dev);
169
170         if (strcmp(bp->bio_attribute, "NAND::device") == 0) {
171                 if (bp->bio_length != sizeof(dev))
172                         return (EFAULT);
173                 bcopy(&dev, bp->bio_data, sizeof(dev));
174         } else {
175                 if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0)
176                         val = cg->oob_size;
177                 else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0)
178                         val = cg->page_size;
179                 else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0)
180                         val = cg->block_size;
181                 else
182                         return (-1);
183                 if (bp->bio_length != sizeof(val))
184                         return (EFAULT);
185                 bcopy(&val, bp->bio_data, sizeof(val));
186         }
187         bp->bio_completed = bp->bio_length;
188         return (0);
189 }
190
191 static int
192 nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag,
193     struct thread *td)
194 {
195         struct nand_chip *chip;
196         struct chip_geom  *cg;
197         struct nand_oob_rw *oob_rw = NULL;
198         struct nand_raw_rw *raw_rw = NULL;
199         device_t nandbus;
200         size_t bufsize = 0, len = 0;
201         size_t raw_size;
202         off_t off;
203         uint8_t *buf = NULL;
204         int ret = 0;
205         uint8_t status;
206
207         chip = (struct nand_chip *)ndisk->d_drv1;
208         cg = &chip->chip_geom;
209         nandbus = device_get_parent(chip->dev);
210
211         if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
212                 raw_rw = (struct nand_raw_rw *)data;
213                 raw_size =  cg->pgs_per_blk * (cg->page_size + cg->oob_size);
214
215                 /* Check if len is not bigger than chip size */
216                 if (raw_rw->len > raw_size)
217                         return (EFBIG);
218
219                 /*
220                  * Do not ask for too much memory, in case of large transfers
221                  * read/write in 16-pages chunks
222                  */
223                 bufsize = 16 * (cg->page_size + cg->oob_size);
224                 if (raw_rw->len < bufsize)
225                         bufsize = raw_rw->len;
226
227                 buf = malloc(bufsize, M_NAND, M_WAITOK);
228                 len = raw_rw->len;
229                 off = 0;
230         }
231
232         switch (cmd) {
233         case NAND_IO_ERASE:
234                 ret = nand_erase_blocks(chip, ((off_t *)data)[0],
235                     ((off_t *)data)[1]);
236                 break;
237
238         case NAND_IO_OOB_READ:
239                 oob_rw = (struct nand_oob_rw *)data;
240                 ret = nand_oob_access(chip, oob_rw->page, 0,
241                     oob_rw->len, oob_rw->data, 0);
242                 break;
243
244         case NAND_IO_OOB_PROG:
245                 oob_rw = (struct nand_oob_rw *)data;
246                 ret = nand_oob_access(chip, oob_rw->page, 0,
247                     oob_rw->len, oob_rw->data, 1);
248                 break;
249
250         case NAND_IO_GET_STATUS:
251                 NANDBUS_LOCK(nandbus);
252                 ret = NANDBUS_GET_STATUS(nandbus, &status);
253                 if (ret == 0)
254                         *(uint8_t *)data = status;
255                 NANDBUS_UNLOCK(nandbus);
256                 break;
257
258         case NAND_IO_RAW_PROG:
259                 while (len > 0) {
260                         if (len < bufsize)
261                                 bufsize = len;
262
263                         ret = copyin(raw_rw->data + off, buf, bufsize);
264                         if (ret)
265                                 break;
266                         ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
267                             bufsize);
268                         if (ret)
269                                 break;
270                         len -= bufsize;
271                         off += bufsize;
272                 }
273                 break;
274
275         case NAND_IO_RAW_READ:
276                 while (len > 0) {
277                         if (len < bufsize)
278                                 bufsize = len;
279
280                         ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
281                             bufsize);
282                         if (ret)
283                                 break;
284
285                         ret = copyout(buf, raw_rw->data + off, bufsize);
286                         if (ret)
287                                 break;
288                         len -= bufsize;
289                         off += bufsize;
290                 }
291                 break;
292
293         case NAND_IO_GET_CHIP_PARAM:
294                 nand_get_chip_param(chip, (struct chip_param_io *)data);
295                 break;
296
297         default:
298                 printf("Unknown nand_ioctl request \n");
299                 ret = EIO;
300         }
301
302         if (buf)
303                 free(buf, M_NAND);
304
305         return (ret);
306 }
307
308 static void
309 nand_io_proc(void *arg, int pending)
310 {
311         struct nand_chip *chip = arg;
312         struct bio *bp;
313         int err = 0;
314
315         for (;;) {
316                 mtx_lock(&chip->qlock);
317                 bp = bioq_takefirst(&chip->bioq);
318                 mtx_unlock(&chip->qlock);
319                 if (bp == NULL)
320                         break;
321
322                 if (bp->bio_driver1 == BIO_NAND_STD) {
323                         if ((bp->bio_cmd & BIO_READ) == BIO_READ) {
324                                 err = nand_read(chip,
325                                     bp->bio_offset & 0xffffffff,
326                                     bp->bio_data, bp->bio_bcount);
327                         } else if ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE) {
328                                 err = nand_write(chip,
329                                     bp->bio_offset & 0xffffffff,
330                                     bp->bio_data, bp->bio_bcount);
331                         }
332                 } else if (bp->bio_driver1 == BIO_NAND_RAW) {
333                         if ((bp->bio_cmd & BIO_READ) == BIO_READ) {
334                                 err = nand_read_raw(chip,
335                                     bp->bio_offset & 0xffffffff,
336                                     bp->bio_data, bp->bio_bcount);
337                         } else if ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE) {
338                                 err = nand_write_raw(chip,
339                                     bp->bio_offset & 0xffffffff,
340                                     bp->bio_data, bp->bio_bcount);
341                         }
342                 } else
343                         panic("Unknown access type in bio->bio_driver1\n");
344
345                 if ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE) {
346                         nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld "
347                             "length %ld\n", chip->num, bp->bio_offset,
348                             bp->bio_bcount);
349                         err = nand_erase_blocks(chip,
350                             bp->bio_offset & 0xffffffff,
351                             bp->bio_bcount);
352                 }
353
354                 if (err == 0 || err == ECC_CORRECTABLE)
355                         bp->bio_resid = 0;
356                 else {
357                         nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] "
358                             "error: %d\n", err);
359
360                         bp->bio_error = EIO;
361                         bp->bio_flags |= BIO_ERROR;
362                         bp->bio_resid = bp->bio_bcount;
363                 }
364                 biodone(bp);
365         }
366 }
367
368 int
369 create_geom_disk(struct nand_chip *chip)
370 {
371         struct disk *ndisk, *rdisk;
372
373         /* Create the disk device */
374         ndisk = disk_alloc();
375         ndisk->d_strategy = nand_strategy;
376         ndisk->d_ioctl = nand_ioctl;
377         ndisk->d_getattr = nand_getattr;
378         ndisk->d_name = "gnand";
379         ndisk->d_drv1 = chip;
380         ndisk->d_maxsize = chip->chip_geom.block_size;
381         ndisk->d_sectorsize = chip->chip_geom.page_size;
382         ndisk->d_mediasize = chip->chip_geom.chip_size;
383         ndisk->d_unit = chip->num +
384             10 * device_get_unit(device_get_parent(chip->dev));
385
386         /*
387          * When using BBT, make two last blocks of device unavailable
388          * to user (because those are used to store BBT table).
389          */
390         if (chip->bbt != NULL)
391                 ndisk->d_mediasize -= (2 * chip->chip_geom.block_size);
392
393         ndisk->d_flags = DISKFLAG_CANDELETE;
394
395         snprintf(ndisk->d_ident, sizeof(ndisk->d_ident),
396             "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
397
398         disk_create(ndisk, DISK_VERSION);
399
400         /* Create the RAW disk device */
401         rdisk = disk_alloc();
402         rdisk->d_strategy = nand_strategy_raw;
403         rdisk->d_ioctl = nand_ioctl;
404         rdisk->d_getattr = nand_getattr;
405         rdisk->d_name = "gnand.raw";
406         rdisk->d_drv1 = chip;
407         rdisk->d_maxsize = chip->chip_geom.block_size;
408         rdisk->d_sectorsize = chip->chip_geom.page_size;
409         rdisk->d_mediasize = chip->chip_geom.chip_size;
410         rdisk->d_unit = chip->num +
411             10 * device_get_unit(device_get_parent(chip->dev));
412
413         rdisk->d_flags = DISKFLAG_CANDELETE;
414
415         snprintf(rdisk->d_ident, sizeof(rdisk->d_ident),
416             "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id,
417             chip->id.dev_id);
418
419         disk_create(rdisk, DISK_VERSION);
420
421         chip->ndisk = ndisk;
422         chip->rdisk = rdisk;
423
424         mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF);
425         bioq_init(&chip->bioq);
426
427         TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
428         chip->tq = taskqueue_create("nand_taskq", M_WAITOK,
429             taskqueue_thread_enqueue, &chip->tq);
430         taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq");
431
432         if (bootverbose)
433                 device_printf(chip->dev, "Created gnand%d for chip [0x%0x, "
434                     "0x%0x]\n", ndisk->d_unit, chip->id.man_id,
435                     chip->id.dev_id);
436
437         return (0);
438 }
439
440 void
441 destroy_geom_disk(struct nand_chip *chip)
442 {
443         struct bio *bp;
444
445         taskqueue_free(chip->tq);
446         disk_destroy(chip->ndisk);
447         disk_destroy(chip->rdisk);
448
449         mtx_lock(&chip->qlock);
450         for (;;) {
451                 bp = bioq_takefirst(&chip->bioq);
452                 if (bp == NULL)
453                         break;
454                 bp->bio_error = EIO;
455                 bp->bio_flags |= BIO_ERROR;
456                 bp->bio_resid = bp->bio_bcount;
457
458                 biodone(bp);
459         }
460         mtx_unlock(&chip->qlock);
461
462         mtx_destroy(&chip->qlock);
463 }