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

unix.superglobalmegacorp.com