File:  [Qemu by Fabrice Bellard] / qemu / hw / nand.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:47:52 2018 UTC (2 years, 7 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

    1: /*
    2:  * Flash NAND memory emulation.  Based on "16M x 8 Bit NAND Flash
    3:  * Memory" datasheet for the KM29U128AT / K9F2808U0A chips from
    4:  * Samsung Electronic.
    5:  *
    6:  * Copyright (c) 2006 Openedhand Ltd.
    7:  * Written by Andrzej Zaborowski <balrog@zabor.org>
    8:  *
    9:  * Support for additional features based on "MT29F2G16ABCWP 2Gx16"
   10:  * datasheet from Micron Technology and "NAND02G-B2C" datasheet
   11:  * from ST Microelectronics.
   12:  *
   13:  * This code is licensed under the GNU GPL v2.
   14:  *
   15:  * Contributions after 2012-01-13 are licensed under the terms of the
   16:  * GNU GPL, version 2 or (at your option) any later version.
   17:  */
   18: 
   19: #ifndef NAND_IO
   20: 
   21: # include "hw.h"
   22: # include "flash.h"
   23: # include "blockdev.h"
   24: # include "sysbus.h"
   25: #include "qemu-error.h"
   26: 
   27: # define NAND_CMD_READ0		0x00
   28: # define NAND_CMD_READ1		0x01
   29: # define NAND_CMD_READ2		0x50
   30: # define NAND_CMD_LPREAD2	0x30
   31: # define NAND_CMD_NOSERIALREAD2	0x35
   32: # define NAND_CMD_RANDOMREAD1	0x05
   33: # define NAND_CMD_RANDOMREAD2	0xe0
   34: # define NAND_CMD_READID	0x90
   35: # define NAND_CMD_RESET		0xff
   36: # define NAND_CMD_PAGEPROGRAM1	0x80
   37: # define NAND_CMD_PAGEPROGRAM2	0x10
   38: # define NAND_CMD_CACHEPROGRAM2	0x15
   39: # define NAND_CMD_BLOCKERASE1	0x60
   40: # define NAND_CMD_BLOCKERASE2	0xd0
   41: # define NAND_CMD_READSTATUS	0x70
   42: # define NAND_CMD_COPYBACKPRG1	0x85
   43: 
   44: # define NAND_IOSTATUS_ERROR	(1 << 0)
   45: # define NAND_IOSTATUS_PLANE0	(1 << 1)
   46: # define NAND_IOSTATUS_PLANE1	(1 << 2)
   47: # define NAND_IOSTATUS_PLANE2	(1 << 3)
   48: # define NAND_IOSTATUS_PLANE3	(1 << 4)
   49: # define NAND_IOSTATUS_BUSY	(1 << 6)
   50: # define NAND_IOSTATUS_UNPROTCT	(1 << 7)
   51: 
   52: # define MAX_PAGE		0x800
   53: # define MAX_OOB		0x40
   54: 
   55: typedef struct NANDFlashState NANDFlashState;
   56: struct NANDFlashState {
   57:     SysBusDevice busdev;
   58:     uint8_t manf_id, chip_id;
   59:     uint8_t buswidth; /* in BYTES */
   60:     int size, pages;
   61:     int page_shift, oob_shift, erase_shift, addr_shift;
   62:     uint8_t *storage;
   63:     BlockDriverState *bdrv;
   64:     int mem_oob;
   65: 
   66:     uint8_t cle, ale, ce, wp, gnd;
   67: 
   68:     uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
   69:     uint8_t *ioaddr;
   70:     int iolen;
   71: 
   72:     uint32_t cmd;
   73:     uint64_t addr;
   74:     int addrlen;
   75:     int status;
   76:     int offset;
   77: 
   78:     void (*blk_write)(NANDFlashState *s);
   79:     void (*blk_erase)(NANDFlashState *s);
   80:     void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
   81: 
   82:     uint32_t ioaddr_vmstate;
   83: };
   84: 
   85: static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
   86: {
   87:     /* Like memcpy() but we logical-AND the data into the destination */
   88:     int i;
   89:     for (i = 0; i < n; i++) {
   90:         dest[i] &= src[i];
   91:     }
   92: }
   93: 
   94: # define NAND_NO_AUTOINCR	0x00000001
   95: # define NAND_BUSWIDTH_16	0x00000002
   96: # define NAND_NO_PADDING	0x00000004
   97: # define NAND_CACHEPRG		0x00000008
   98: # define NAND_COPYBACK		0x00000010
   99: # define NAND_IS_AND		0x00000020
  100: # define NAND_4PAGE_ARRAY	0x00000040
  101: # define NAND_NO_READRDY	0x00000100
  102: # define NAND_SAMSUNG_LP	(NAND_NO_PADDING | NAND_COPYBACK)
  103: 
  104: # define NAND_IO
  105: 
  106: # define PAGE(addr)		((addr) >> ADDR_SHIFT)
  107: # define PAGE_START(page)	(PAGE(page) * (PAGE_SIZE + OOB_SIZE))
  108: # define PAGE_MASK		((1 << ADDR_SHIFT) - 1)
  109: # define OOB_SHIFT		(PAGE_SHIFT - 5)
  110: # define OOB_SIZE		(1 << OOB_SHIFT)
  111: # define SECTOR(addr)		((addr) >> (9 + ADDR_SHIFT - PAGE_SHIFT))
  112: # define SECTOR_OFFSET(addr)	((addr) & ((511 >> PAGE_SHIFT) << 8))
  113: 
  114: # define PAGE_SIZE		256
  115: # define PAGE_SHIFT		8
  116: # define PAGE_SECTORS		1
  117: # define ADDR_SHIFT		8
  118: # include "nand.c"
  119: # define PAGE_SIZE		512
  120: # define PAGE_SHIFT		9
  121: # define PAGE_SECTORS		1
  122: # define ADDR_SHIFT		8
  123: # include "nand.c"
  124: # define PAGE_SIZE		2048
  125: # define PAGE_SHIFT		11
  126: # define PAGE_SECTORS		4
  127: # define ADDR_SHIFT		16
  128: # include "nand.c"
  129: 
  130: /* Information based on Linux drivers/mtd/nand/nand_ids.c */
  131: static const struct {
  132:     int size;
  133:     int width;
  134:     int page_shift;
  135:     int erase_shift;
  136:     uint32_t options;
  137: } nand_flash_ids[0x100] = {
  138:     [0 ... 0xff] = { 0 },
  139: 
  140:     [0x6e] = { 1,	8,	8, 4, 0 },
  141:     [0x64] = { 2,	8,	8, 4, 0 },
  142:     [0x6b] = { 4,	8,	9, 4, 0 },
  143:     [0xe8] = { 1,	8,	8, 4, 0 },
  144:     [0xec] = { 1,	8,	8, 4, 0 },
  145:     [0xea] = { 2,	8,	8, 4, 0 },
  146:     [0xd5] = { 4,	8,	9, 4, 0 },
  147:     [0xe3] = { 4,	8,	9, 4, 0 },
  148:     [0xe5] = { 4,	8,	9, 4, 0 },
  149:     [0xd6] = { 8,	8,	9, 4, 0 },
  150: 
  151:     [0x39] = { 8,	8,	9, 4, 0 },
  152:     [0xe6] = { 8,	8,	9, 4, 0 },
  153:     [0x49] = { 8,	16,	9, 4, NAND_BUSWIDTH_16 },
  154:     [0x59] = { 8,	16,	9, 4, NAND_BUSWIDTH_16 },
  155: 
  156:     [0x33] = { 16,	8,	9, 5, 0 },
  157:     [0x73] = { 16,	8,	9, 5, 0 },
  158:     [0x43] = { 16,	16,	9, 5, NAND_BUSWIDTH_16 },
  159:     [0x53] = { 16,	16,	9, 5, NAND_BUSWIDTH_16 },
  160: 
  161:     [0x35] = { 32,	8,	9, 5, 0 },
  162:     [0x75] = { 32,	8,	9, 5, 0 },
  163:     [0x45] = { 32,	16,	9, 5, NAND_BUSWIDTH_16 },
  164:     [0x55] = { 32,	16,	9, 5, NAND_BUSWIDTH_16 },
  165: 
  166:     [0x36] = { 64,	8,	9, 5, 0 },
  167:     [0x76] = { 64,	8,	9, 5, 0 },
  168:     [0x46] = { 64,	16,	9, 5, NAND_BUSWIDTH_16 },
  169:     [0x56] = { 64,	16,	9, 5, NAND_BUSWIDTH_16 },
  170: 
  171:     [0x78] = { 128,	8,	9, 5, 0 },
  172:     [0x39] = { 128,	8,	9, 5, 0 },
  173:     [0x79] = { 128,	8,	9, 5, 0 },
  174:     [0x72] = { 128,	16,	9, 5, NAND_BUSWIDTH_16 },
  175:     [0x49] = { 128,	16,	9, 5, NAND_BUSWIDTH_16 },
  176:     [0x74] = { 128,	16,	9, 5, NAND_BUSWIDTH_16 },
  177:     [0x59] = { 128,	16,	9, 5, NAND_BUSWIDTH_16 },
  178: 
  179:     [0x71] = { 256,	8,	9, 5, 0 },
  180: 
  181:     /*
  182:      * These are the new chips with large page size. The pagesize and the
  183:      * erasesize is determined from the extended id bytes
  184:      */
  185: # define LP_OPTIONS	(NAND_SAMSUNG_LP | NAND_NO_READRDY | NAND_NO_AUTOINCR)
  186: # define LP_OPTIONS16	(LP_OPTIONS | NAND_BUSWIDTH_16)
  187: 
  188:     /* 512 Megabit */
  189:     [0xa2] = { 64,	8,	0, 0, LP_OPTIONS },
  190:     [0xf2] = { 64,	8,	0, 0, LP_OPTIONS },
  191:     [0xb2] = { 64,	16,	0, 0, LP_OPTIONS16 },
  192:     [0xc2] = { 64,	16,	0, 0, LP_OPTIONS16 },
  193: 
  194:     /* 1 Gigabit */
  195:     [0xa1] = { 128,	8,	0, 0, LP_OPTIONS },
  196:     [0xf1] = { 128,	8,	0, 0, LP_OPTIONS },
  197:     [0xb1] = { 128,	16,	0, 0, LP_OPTIONS16 },
  198:     [0xc1] = { 128,	16,	0, 0, LP_OPTIONS16 },
  199: 
  200:     /* 2 Gigabit */
  201:     [0xaa] = { 256,	8,	0, 0, LP_OPTIONS },
  202:     [0xda] = { 256,	8,	0, 0, LP_OPTIONS },
  203:     [0xba] = { 256,	16,	0, 0, LP_OPTIONS16 },
  204:     [0xca] = { 256,	16,	0, 0, LP_OPTIONS16 },
  205: 
  206:     /* 4 Gigabit */
  207:     [0xac] = { 512,	8,	0, 0, LP_OPTIONS },
  208:     [0xdc] = { 512,	8,	0, 0, LP_OPTIONS },
  209:     [0xbc] = { 512,	16,	0, 0, LP_OPTIONS16 },
  210:     [0xcc] = { 512,	16,	0, 0, LP_OPTIONS16 },
  211: 
  212:     /* 8 Gigabit */
  213:     [0xa3] = { 1024,	8,	0, 0, LP_OPTIONS },
  214:     [0xd3] = { 1024,	8,	0, 0, LP_OPTIONS },
  215:     [0xb3] = { 1024,	16,	0, 0, LP_OPTIONS16 },
  216:     [0xc3] = { 1024,	16,	0, 0, LP_OPTIONS16 },
  217: 
  218:     /* 16 Gigabit */
  219:     [0xa5] = { 2048,	8,	0, 0, LP_OPTIONS },
  220:     [0xd5] = { 2048,	8,	0, 0, LP_OPTIONS },
  221:     [0xb5] = { 2048,	16,	0, 0, LP_OPTIONS16 },
  222:     [0xc5] = { 2048,	16,	0, 0, LP_OPTIONS16 },
  223: };
  224: 
  225: static void nand_reset(DeviceState *dev)
  226: {
  227:     NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
  228:     s->cmd = NAND_CMD_READ0;
  229:     s->addr = 0;
  230:     s->addrlen = 0;
  231:     s->iolen = 0;
  232:     s->offset = 0;
  233:     s->status &= NAND_IOSTATUS_UNPROTCT;
  234: }
  235: 
  236: static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
  237: {
  238:     s->ioaddr[s->iolen++] = value;
  239:     for (value = s->buswidth; --value;) {
  240:         s->ioaddr[s->iolen++] = 0;
  241:     }
  242: }
  243: 
  244: static void nand_command(NANDFlashState *s)
  245: {
  246:     unsigned int offset;
  247:     switch (s->cmd) {
  248:     case NAND_CMD_READ0:
  249:         s->iolen = 0;
  250:         break;
  251: 
  252:     case NAND_CMD_READID:
  253:         s->ioaddr = s->io;
  254:         s->iolen = 0;
  255:         nand_pushio_byte(s, s->manf_id);
  256:         nand_pushio_byte(s, s->chip_id);
  257:         nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */
  258:         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
  259:             /* Page Size, Block Size, Spare Size; bit 6 indicates
  260:              * 8 vs 16 bit width NAND.
  261:              */
  262:             nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15);
  263:         } else {
  264:             nand_pushio_byte(s, 0xc0); /* Multi-plane */
  265:         }
  266:         break;
  267: 
  268:     case NAND_CMD_RANDOMREAD2:
  269:     case NAND_CMD_NOSERIALREAD2:
  270:         if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
  271:             break;
  272:         offset = s->addr & ((1 << s->addr_shift) - 1);
  273:         s->blk_load(s, s->addr, offset);
  274:         if (s->gnd)
  275:             s->iolen = (1 << s->page_shift) - offset;
  276:         else
  277:             s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
  278:         break;
  279: 
  280:     case NAND_CMD_RESET:
  281:         nand_reset(&s->busdev.qdev);
  282:         break;
  283: 
  284:     case NAND_CMD_PAGEPROGRAM1:
  285:         s->ioaddr = s->io;
  286:         s->iolen = 0;
  287:         break;
  288: 
  289:     case NAND_CMD_PAGEPROGRAM2:
  290:         if (s->wp) {
  291:             s->blk_write(s);
  292:         }
  293:         break;
  294: 
  295:     case NAND_CMD_BLOCKERASE1:
  296:         break;
  297: 
  298:     case NAND_CMD_BLOCKERASE2:
  299:         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
  300:             s->addr <<= 16;
  301:         else
  302:             s->addr <<= 8;
  303: 
  304:         if (s->wp) {
  305:             s->blk_erase(s);
  306:         }
  307:         break;
  308: 
  309:     case NAND_CMD_READSTATUS:
  310:         s->ioaddr = s->io;
  311:         s->iolen = 0;
  312:         nand_pushio_byte(s, s->status);
  313:         break;
  314: 
  315:     default:
  316:         printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
  317:     }
  318: }
  319: 
  320: static void nand_pre_save(void *opaque)
  321: {
  322:     NANDFlashState *s = opaque;
  323: 
  324:     s->ioaddr_vmstate = s->ioaddr - s->io;
  325: }
  326: 
  327: static int nand_post_load(void *opaque, int version_id)
  328: {
  329:     NANDFlashState *s = opaque;
  330: 
  331:     if (s->ioaddr_vmstate > sizeof(s->io)) {
  332:         return -EINVAL;
  333:     }
  334:     s->ioaddr = s->io + s->ioaddr_vmstate;
  335: 
  336:     return 0;
  337: }
  338: 
  339: static const VMStateDescription vmstate_nand = {
  340:     .name = "nand",
  341:     .version_id = 1,
  342:     .minimum_version_id = 1,
  343:     .minimum_version_id_old = 1,
  344:     .pre_save = nand_pre_save,
  345:     .post_load = nand_post_load,
  346:     .fields      = (VMStateField[]) {
  347:         VMSTATE_UINT8(cle, NANDFlashState),
  348:         VMSTATE_UINT8(ale, NANDFlashState),
  349:         VMSTATE_UINT8(ce, NANDFlashState),
  350:         VMSTATE_UINT8(wp, NANDFlashState),
  351:         VMSTATE_UINT8(gnd, NANDFlashState),
  352:         VMSTATE_BUFFER(io, NANDFlashState),
  353:         VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
  354:         VMSTATE_INT32(iolen, NANDFlashState),
  355:         VMSTATE_UINT32(cmd, NANDFlashState),
  356:         VMSTATE_UINT64(addr, NANDFlashState),
  357:         VMSTATE_INT32(addrlen, NANDFlashState),
  358:         VMSTATE_INT32(status, NANDFlashState),
  359:         VMSTATE_INT32(offset, NANDFlashState),
  360:         /* XXX: do we want to save s->storage too? */
  361:         VMSTATE_END_OF_LIST()
  362:     }
  363: };
  364: 
  365: static int nand_device_init(SysBusDevice *dev)
  366: {
  367:     int pagesize;
  368:     NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev);
  369: 
  370:     s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
  371:     s->size = nand_flash_ids[s->chip_id].size << 20;
  372:     if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
  373:         s->page_shift = 11;
  374:         s->erase_shift = 6;
  375:     } else {
  376:         s->page_shift = nand_flash_ids[s->chip_id].page_shift;
  377:         s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
  378:     }
  379: 
  380:     switch (1 << s->page_shift) {
  381:     case 256:
  382:         nand_init_256(s);
  383:         break;
  384:     case 512:
  385:         nand_init_512(s);
  386:         break;
  387:     case 2048:
  388:         nand_init_2048(s);
  389:         break;
  390:     default:
  391:         error_report("Unsupported NAND block size");
  392:         return -1;
  393:     }
  394: 
  395:     pagesize = 1 << s->oob_shift;
  396:     s->mem_oob = 1;
  397:     if (s->bdrv) {
  398:         if (bdrv_is_read_only(s->bdrv)) {
  399:             error_report("Can't use a read-only drive");
  400:             return -1;
  401:         }
  402:         if (bdrv_getlength(s->bdrv) >=
  403:                 (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
  404:             pagesize = 0;
  405:             s->mem_oob = 0;
  406:         }
  407:     } else {
  408:         pagesize += 1 << s->page_shift;
  409:     }
  410:     if (pagesize) {
  411:         s->storage = (uint8_t *) memset(g_malloc(s->pages * pagesize),
  412:                         0xff, s->pages * pagesize);
  413:     }
  414:     /* Give s->ioaddr a sane value in case we save state before it is used. */
  415:     s->ioaddr = s->io;
  416: 
  417:     return 0;
  418: }
  419: 
  420: static Property nand_properties[] = {
  421:     DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
  422:     DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
  423:     DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
  424:     DEFINE_PROP_END_OF_LIST(),
  425: };
  426: 
  427: static void nand_class_init(ObjectClass *klass, void *data)
  428: {
  429:     DeviceClass *dc = DEVICE_CLASS(klass);
  430:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  431: 
  432:     k->init = nand_device_init;
  433:     dc->reset = nand_reset;
  434:     dc->vmsd = &vmstate_nand;
  435:     dc->props = nand_properties;
  436: }
  437: 
  438: static TypeInfo nand_info = {
  439:     .name          = "nand",
  440:     .parent        = TYPE_SYS_BUS_DEVICE,
  441:     .instance_size = sizeof(NANDFlashState),
  442:     .class_init    = nand_class_init,
  443: };
  444: 
  445: static void nand_register_types(void)
  446: {
  447:     type_register_static(&nand_info);
  448: }
  449: 
  450: /*
  451:  * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins.  Chip
  452:  * outputs are R/B and eight I/O pins.
  453:  *
  454:  * CE, WP and R/B are active low.
  455:  */
  456: void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
  457:                   uint8_t ce, uint8_t wp, uint8_t gnd)
  458: {
  459:     NANDFlashState *s = (NANDFlashState *) dev;
  460:     s->cle = cle;
  461:     s->ale = ale;
  462:     s->ce = ce;
  463:     s->wp = wp;
  464:     s->gnd = gnd;
  465:     if (wp)
  466:         s->status |= NAND_IOSTATUS_UNPROTCT;
  467:     else
  468:         s->status &= ~NAND_IOSTATUS_UNPROTCT;
  469: }
  470: 
  471: void nand_getpins(DeviceState *dev, int *rb)
  472: {
  473:     *rb = 1;
  474: }
  475: 
  476: void nand_setio(DeviceState *dev, uint32_t value)
  477: {
  478:     int i;
  479:     NANDFlashState *s = (NANDFlashState *) dev;
  480:     if (!s->ce && s->cle) {
  481:         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
  482:             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
  483:                 return;
  484:             if (value == NAND_CMD_RANDOMREAD1) {
  485:                 s->addr &= ~((1 << s->addr_shift) - 1);
  486:                 s->addrlen = 0;
  487:                 return;
  488:             }
  489:         }
  490:         if (value == NAND_CMD_READ0)
  491:             s->offset = 0;
  492: 	else if (value == NAND_CMD_READ1) {
  493:             s->offset = 0x100;
  494:             value = NAND_CMD_READ0;
  495:         }
  496: 	else if (value == NAND_CMD_READ2) {
  497:             s->offset = 1 << s->page_shift;
  498:             value = NAND_CMD_READ0;
  499:         }
  500: 
  501:         s->cmd = value;
  502: 
  503:         if (s->cmd == NAND_CMD_READSTATUS ||
  504:                 s->cmd == NAND_CMD_PAGEPROGRAM2 ||
  505:                 s->cmd == NAND_CMD_BLOCKERASE1 ||
  506:                 s->cmd == NAND_CMD_BLOCKERASE2 ||
  507:                 s->cmd == NAND_CMD_NOSERIALREAD2 ||
  508:                 s->cmd == NAND_CMD_RANDOMREAD2 ||
  509:                 s->cmd == NAND_CMD_RESET)
  510:             nand_command(s);
  511: 
  512:         if (s->cmd != NAND_CMD_RANDOMREAD2) {
  513:             s->addrlen = 0;
  514:         }
  515:     }
  516: 
  517:     if (s->ale) {
  518:         unsigned int shift = s->addrlen * 8;
  519:         unsigned int mask = ~(0xff << shift);
  520:         unsigned int v = value << shift;
  521: 
  522:         s->addr = (s->addr & mask) | v;
  523:         s->addrlen ++;
  524: 
  525:         switch (s->addrlen) {
  526:         case 1:
  527:             if (s->cmd == NAND_CMD_READID) {
  528:                 nand_command(s);
  529:             }
  530:             break;
  531:         case 2: /* fix cache address as a byte address */
  532:             s->addr <<= (s->buswidth - 1);
  533:             break;
  534:         case 3:
  535:             if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
  536:                     (s->cmd == NAND_CMD_READ0 ||
  537:                      s->cmd == NAND_CMD_PAGEPROGRAM1)) {
  538:                 nand_command(s);
  539:             }
  540:             break;
  541:         case 4:
  542:             if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
  543:                     nand_flash_ids[s->chip_id].size < 256 && /* 1Gb or less */
  544:                     (s->cmd == NAND_CMD_READ0 ||
  545:                      s->cmd == NAND_CMD_PAGEPROGRAM1)) {
  546:                 nand_command(s);
  547:             }
  548:             break;
  549:         case 5:
  550:             if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
  551:                     nand_flash_ids[s->chip_id].size >= 256 && /* 2Gb or more */
  552:                     (s->cmd == NAND_CMD_READ0 ||
  553:                      s->cmd == NAND_CMD_PAGEPROGRAM1)) {
  554:                 nand_command(s);
  555:             }
  556:             break;
  557:         default:
  558:             break;
  559:         }
  560:     }
  561: 
  562:     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
  563:         if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) {
  564:             for (i = s->buswidth; i--; value >>= 8) {
  565:                 s->io[s->iolen ++] = (uint8_t) (value & 0xff);
  566:             }
  567:         }
  568:     } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
  569:         if ((s->addr & ((1 << s->addr_shift) - 1)) <
  570:                 (1 << s->page_shift) + (1 << s->oob_shift)) {
  571:             for (i = s->buswidth; i--; s->addr++, value >>= 8) {
  572:                 s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] =
  573:                     (uint8_t) (value & 0xff);
  574:             }
  575:         }
  576:     }
  577: }
  578: 
  579: uint32_t nand_getio(DeviceState *dev)
  580: {
  581:     int offset;
  582:     uint32_t x = 0;
  583:     NANDFlashState *s = (NANDFlashState *) dev;
  584: 
  585:     /* Allow sequential reading */
  586:     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
  587:         offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
  588:         s->offset = 0;
  589: 
  590:         s->blk_load(s, s->addr, offset);
  591:         if (s->gnd)
  592:             s->iolen = (1 << s->page_shift) - offset;
  593:         else
  594:             s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
  595:     }
  596: 
  597:     if (s->ce || s->iolen <= 0)
  598:         return 0;
  599: 
  600:     for (offset = s->buswidth; offset--;) {
  601:         x |= s->ioaddr[offset] << (offset << 3);
  602:     }
  603:     /* after receiving READ STATUS command all subsequent reads will
  604:      * return the status register value until another command is issued
  605:      */
  606:     if (s->cmd != NAND_CMD_READSTATUS) {
  607:         s->addr   += s->buswidth;
  608:         s->ioaddr += s->buswidth;
  609:         s->iolen  -= s->buswidth;
  610:     }
  611:     return x;
  612: }
  613: 
  614: uint32_t nand_getbuswidth(DeviceState *dev)
  615: {
  616:     NANDFlashState *s = (NANDFlashState *) dev;
  617:     return s->buswidth << 3;
  618: }
  619: 
  620: DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
  621: {
  622:     DeviceState *dev;
  623: 
  624:     if (nand_flash_ids[chip_id].size == 0) {
  625:         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
  626:     }
  627:     dev = qdev_create(NULL, "nand");
  628:     qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
  629:     qdev_prop_set_uint8(dev, "chip_id", chip_id);
  630:     if (bdrv) {
  631:         qdev_prop_set_drive_nofail(dev, "drive", bdrv);
  632:     }
  633: 
  634:     qdev_init_nofail(dev);
  635:     return dev;
  636: }
  637: 
  638: type_init(nand_register_types)
  639: 
  640: #else
  641: 
  642: /* Program a single page */
  643: static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
  644: {
  645:     uint64_t off, page, sector, soff;
  646:     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
  647:     if (PAGE(s->addr) >= s->pages)
  648:         return;
  649: 
  650:     if (!s->bdrv) {
  651:         mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
  652:                         s->offset, s->io, s->iolen);
  653:     } else if (s->mem_oob) {
  654:         sector = SECTOR(s->addr);
  655:         off = (s->addr & PAGE_MASK) + s->offset;
  656:         soff = SECTOR_OFFSET(s->addr);
  657:         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
  658:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
  659:             return;
  660:         }
  661: 
  662:         mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
  663:         if (off + s->iolen > PAGE_SIZE) {
  664:             page = PAGE(s->addr);
  665:             mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
  666:                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
  667:         }
  668: 
  669:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
  670:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
  671:     } else {
  672:         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
  673:         sector = off >> 9;
  674:         soff = off & 0x1ff;
  675:         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
  676:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
  677:             return;
  678:         }
  679: 
  680:         mem_and(iobuf + soff, s->io, s->iolen);
  681: 
  682:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
  683:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
  684:     }
  685:     s->offset = 0;
  686: }
  687: 
  688: /* Erase a single block */
  689: static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
  690: {
  691:     uint64_t i, page, addr;
  692:     uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
  693:     addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
  694: 
  695:     if (PAGE(addr) >= s->pages)
  696:         return;
  697: 
  698:     if (!s->bdrv) {
  699:         memset(s->storage + PAGE_START(addr),
  700:                         0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift);
  701:     } else if (s->mem_oob) {
  702:         memset(s->storage + (PAGE(addr) << OOB_SHIFT),
  703:                         0xff, OOB_SIZE << s->erase_shift);
  704:         i = SECTOR(addr);
  705:         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
  706:         for (; i < page; i ++)
  707:             if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
  708:                 printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
  709:     } else {
  710:         addr = PAGE_START(addr);
  711:         page = addr >> 9;
  712:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
  713:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
  714:         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
  715:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
  716:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
  717: 
  718:         memset(iobuf, 0xff, 0x200);
  719:         i = (addr & ~0x1ff) + 0x200;
  720:         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
  721:                         i < addr; i += 0x200)
  722:             if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
  723:                 printf("%s: write error in sector %" PRIu64 "\n",
  724:                        __func__, i >> 9);
  725: 
  726:         page = i >> 9;
  727:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
  728:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
  729:         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
  730:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
  731:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
  732:     }
  733: }
  734: 
  735: static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
  736:                 uint64_t addr, int offset)
  737: {
  738:     if (PAGE(addr) >= s->pages)
  739:         return;
  740: 
  741:     if (s->bdrv) {
  742:         if (s->mem_oob) {
  743:             if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
  744:                 printf("%s: read error in sector %" PRIu64 "\n",
  745:                                 __func__, SECTOR(addr));
  746:             memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
  747:                             s->storage + (PAGE(s->addr) << OOB_SHIFT),
  748:                             OOB_SIZE);
  749:             s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
  750:         } else {
  751:             if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
  752:                                     s->io, (PAGE_SECTORS + 2)) == -1)
  753:                 printf("%s: read error in sector %" PRIu64 "\n",
  754:                                 __func__, PAGE_START(addr) >> 9);
  755:             s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
  756:         }
  757:     } else {
  758:         memcpy(s->io, s->storage + PAGE_START(s->addr) +
  759:                         offset, PAGE_SIZE + OOB_SIZE - offset);
  760:         s->ioaddr = s->io;
  761:     }
  762: }
  763: 
  764: static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)
  765: {
  766:     s->oob_shift = PAGE_SHIFT - 5;
  767:     s->pages = s->size >> PAGE_SHIFT;
  768:     s->addr_shift = ADDR_SHIFT;
  769: 
  770:     s->blk_erase = glue(nand_blk_erase_, PAGE_SIZE);
  771:     s->blk_write = glue(nand_blk_write_, PAGE_SIZE);
  772:     s->blk_load = glue(nand_blk_load_, PAGE_SIZE);
  773: }
  774: 
  775: # undef PAGE_SIZE
  776: # undef PAGE_SHIFT
  777: # undef PAGE_SECTORS
  778: # undef ADDR_SHIFT
  779: #endif	/* NAND_IO */

unix.superglobalmegacorp.com