Annotation of qemu/hw/nand.c, revision 1.1.1.8

1.1       root        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:  *
1.1.1.7   root        9:  * Support for additional features based on "MT29F2G16ABCWP 2Gx16"
                     10:  * datasheet from Micron Technology and "NAND02G-B2C" datasheet
                     11:  * from ST Microelectronics.
                     12:  *
1.1       root       13:  * This code is licensed under the GNU GPL v2.
1.1.1.8 ! root       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.
1.1       root       17:  */
                     18: 
                     19: #ifndef NAND_IO
                     20: 
                     21: # include "hw.h"
                     22: # include "flash.h"
1.1.1.5   root       23: # include "blockdev.h"
1.1.1.7   root       24: # include "sysbus.h"
                     25: #include "qemu-error.h"
1.1       root       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: 
1.1.1.7   root       55: typedef struct NANDFlashState NANDFlashState;
1.1.1.3   root       56: struct NANDFlashState {
1.1.1.7   root       57:     SysBusDevice busdev;
1.1       root       58:     uint8_t manf_id, chip_id;
1.1.1.7   root       59:     uint8_t buswidth; /* in BYTES */
1.1       root       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: 
1.1.1.6   root       66:     uint8_t cle, ale, ce, wp, gnd;
1.1       root       67: 
                     68:     uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
                     69:     uint8_t *ioaddr;
                     70:     int iolen;
                     71: 
1.1.1.7   root       72:     uint32_t cmd;
                     73:     uint64_t addr;
1.1       root       74:     int addrlen;
                     75:     int status;
                     76:     int offset;
                     77: 
1.1.1.3   root       78:     void (*blk_write)(NANDFlashState *s);
                     79:     void (*blk_erase)(NANDFlashState *s);
1.1.1.7   root       80:     void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
1.1.1.6   root       81: 
                     82:     uint32_t ioaddr_vmstate;
1.1       root       83: };
                     84: 
1.1.1.7   root       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: 
1.1       root       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 */
1.1.1.3   root      131: static const struct {
1.1       root      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: 
1.1.1.7   root      225: static void nand_reset(DeviceState *dev)
1.1       root      226: {
1.1.1.7   root      227:     NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
1.1       root      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: 
1.1.1.7   root      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: 
1.1.1.3   root      244: static void nand_command(NANDFlashState *s)
1.1       root      245: {
1.1.1.5   root      246:     unsigned int offset;
1.1       root      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;
1.1.1.7   root      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:         }
1.1       root      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;
1.1.1.5   root      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;
1.1       root      278:         break;
                    279: 
                    280:     case NAND_CMD_RESET:
1.1.1.7   root      281:         nand_reset(&s->busdev.qdev);
1.1       root      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;
1.1.1.7   root      311:         s->iolen = 0;
                    312:         nand_pushio_byte(s, s->status);
1.1       root      313:         break;
                    314: 
                    315:     default:
                    316:         printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
                    317:     }
                    318: }
                    319: 
1.1.1.6   root      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)
1.1       root      328: {
1.1.1.6   root      329:     NANDFlashState *s = opaque;
                    330: 
                    331:     if (s->ioaddr_vmstate > sizeof(s->io)) {
1.1       root      332:         return -EINVAL;
1.1.1.6   root      333:     }
                    334:     s->ioaddr = s->io + s->ioaddr_vmstate;
1.1       root      335: 
                    336:     return 0;
                    337: }
                    338: 
1.1.1.6   root      339: static const VMStateDescription vmstate_nand = {
                    340:     .name = "nand",
1.1.1.7   root      341:     .version_id = 1,
                    342:     .minimum_version_id = 1,
                    343:     .minimum_version_id_old = 1,
1.1.1.6   root      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),
1.1.1.7   root      356:         VMSTATE_UINT64(addr, NANDFlashState),
1.1.1.6   root      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: 
1.1.1.7   root      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: 
1.1.1.8 ! root      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,
1.1.1.7   root      443: };
                    444: 
1.1.1.8 ! root      445: static void nand_register_types(void)
1.1.1.7   root      446: {
1.1.1.8 ! root      447:     type_register_static(&nand_info);
1.1.1.7   root      448: }
                    449: 
1.1       root      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:  */
1.1.1.7   root      456: void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
1.1.1.6   root      457:                   uint8_t ce, uint8_t wp, uint8_t gnd)
1.1       root      458: {
1.1.1.7   root      459:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      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: 
1.1.1.7   root      471: void nand_getpins(DeviceState *dev, int *rb)
1.1       root      472: {
                    473:     *rb = 1;
                    474: }
                    475: 
1.1.1.7   root      476: void nand_setio(DeviceState *dev, uint32_t value)
1.1       root      477: {
1.1.1.7   root      478:     int i;
                    479:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      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) {
1.1.1.5   root      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;
1.1       root      523:         s->addrlen ++;
                    524: 
1.1.1.7   root      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:         }
1.1       root      560:     }
                    561: 
                    562:     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
1.1.1.7   root      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:         }
1.1       root      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)) {
1.1.1.7   root      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:             }
1.1       root      575:         }
                    576:     }
                    577: }
                    578: 
1.1.1.7   root      579: uint32_t nand_getio(DeviceState *dev)
1.1       root      580: {
                    581:     int offset;
1.1.1.7   root      582:     uint32_t x = 0;
                    583:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      584: 
                    585:     /* Allow sequential reading */
                    586:     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
1.1.1.7   root      587:         offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
1.1       root      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: 
1.1.1.7   root      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;
1.1       root      612: }
                    613: 
1.1.1.7   root      614: uint32_t nand_getbuswidth(DeviceState *dev)
1.1       root      615: {
1.1.1.7   root      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;
1.1       root      623: 
                    624:     if (nand_flash_ids[chip_id].size == 0) {
1.1.1.3   root      625:         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
1.1       root      626:     }
1.1.1.7   root      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);
1.1       root      632:     }
                    633: 
1.1.1.7   root      634:     qdev_init_nofail(dev);
                    635:     return dev;
1.1       root      636: }
                    637: 
1.1.1.8 ! root      638: type_init(nand_register_types)
1.1       root      639: 
                    640: #else
                    641: 
                    642: /* Program a single page */
1.1.1.3   root      643: static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      644: {
1.1.1.7   root      645:     uint64_t off, page, sector, soff;
1.1       root      646:     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
                    647:     if (PAGE(s->addr) >= s->pages)
                    648:         return;
                    649: 
                    650:     if (!s->bdrv) {
1.1.1.7   root      651:         mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
1.1       root      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) {
1.1.1.7   root      658:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      659:             return;
                    660:         }
                    661: 
1.1.1.7   root      662:         mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
1.1       root      663:         if (off + s->iolen > PAGE_SIZE) {
                    664:             page = PAGE(s->addr);
1.1.1.7   root      665:             mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
1.1       root      666:                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
                    667:         }
                    668: 
                    669:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
1.1.1.7   root      670:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      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) {
1.1.1.7   root      676:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      677:             return;
                    678:         }
                    679: 
1.1.1.7   root      680:         mem_and(iobuf + soff, s->io, s->iolen);
1.1       root      681: 
                    682:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
1.1.1.7   root      683:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      684:     }
                    685:     s->offset = 0;
                    686: }
                    687: 
                    688: /* Erase a single block */
1.1.1.3   root      689: static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      690: {
1.1.1.7   root      691:     uint64_t i, page, addr;
1.1       root      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)
1.1.1.7   root      708:                 printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
1.1       root      709:     } else {
                    710:         addr = PAGE_START(addr);
                    711:         page = addr >> 9;
                    712:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7   root      713:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
1.1       root      714:         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
                    715:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7   root      716:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
1.1       root      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)
1.1.1.7   root      723:                 printf("%s: write error in sector %" PRIu64 "\n",
                    724:                        __func__, i >> 9);
1.1       root      725: 
                    726:         page = i >> 9;
                    727:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7   root      728:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
1.1       root      729:         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
                    730:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7   root      731:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
1.1       root      732:     }
                    733: }
                    734: 
1.1.1.3   root      735: static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
1.1.1.7   root      736:                 uint64_t addr, int offset)
1.1       root      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)
1.1.1.7   root      744:                 printf("%s: read error in sector %" PRIu64 "\n",
                    745:                                 __func__, SECTOR(addr));
1.1       root      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)
1.1.1.7   root      753:                 printf("%s: read error in sector %" PRIu64 "\n",
                    754:                                 __func__, PAGE_START(addr) >> 9);
1.1       root      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: 
1.1.1.3   root      764: static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      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