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

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 <[email protected]>
                      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.
                     14:  */
                     15: 
                     16: #ifndef NAND_IO
                     17: 
                     18: # include "hw.h"
                     19: # include "flash.h"
1.1.1.5   root       20: # include "blockdev.h"
1.1.1.7 ! root       21: # include "sysbus.h"
        !            22: #include "qemu-error.h"
1.1       root       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: 
1.1.1.7 ! root       52: typedef struct NANDFlashState NANDFlashState;
1.1.1.3   root       53: struct NANDFlashState {
1.1.1.7 ! root       54:     SysBusDevice busdev;
1.1       root       55:     uint8_t manf_id, chip_id;
1.1.1.7 ! root       56:     uint8_t buswidth; /* in BYTES */
1.1       root       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: 
1.1.1.6   root       63:     uint8_t cle, ale, ce, wp, gnd;
1.1       root       64: 
                     65:     uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
                     66:     uint8_t *ioaddr;
                     67:     int iolen;
                     68: 
1.1.1.7 ! root       69:     uint32_t cmd;
        !            70:     uint64_t addr;
1.1       root       71:     int addrlen;
                     72:     int status;
                     73:     int offset;
                     74: 
1.1.1.3   root       75:     void (*blk_write)(NANDFlashState *s);
                     76:     void (*blk_erase)(NANDFlashState *s);
1.1.1.7 ! root       77:     void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
1.1.1.6   root       78: 
                     79:     uint32_t ioaddr_vmstate;
1.1       root       80: };
                     81: 
1.1.1.7 ! root       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: 
1.1       root       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 */
1.1.1.3   root      128: static const struct {
1.1       root      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: 
1.1.1.7 ! root      222: static void nand_reset(DeviceState *dev)
1.1       root      223: {
1.1.1.7 ! root      224:     NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
1.1       root      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: 
1.1.1.7 ! root      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: 
1.1.1.3   root      241: static void nand_command(NANDFlashState *s)
1.1       root      242: {
1.1.1.5   root      243:     unsigned int offset;
1.1       root      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;
1.1.1.7 ! root      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:         }
1.1       root      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;
1.1.1.5   root      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;
1.1       root      275:         break;
                    276: 
                    277:     case NAND_CMD_RESET:
1.1.1.7 ! root      278:         nand_reset(&s->busdev.qdev);
1.1       root      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;
1.1.1.7 ! root      308:         s->iolen = 0;
        !           309:         nand_pushio_byte(s, s->status);
1.1       root      310:         break;
                    311: 
                    312:     default:
                    313:         printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
                    314:     }
                    315: }
                    316: 
1.1.1.6   root      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)
1.1       root      325: {
1.1.1.6   root      326:     NANDFlashState *s = opaque;
                    327: 
                    328:     if (s->ioaddr_vmstate > sizeof(s->io)) {
1.1       root      329:         return -EINVAL;
1.1.1.6   root      330:     }
                    331:     s->ioaddr = s->io + s->ioaddr_vmstate;
1.1       root      332: 
                    333:     return 0;
                    334: }
                    335: 
1.1.1.6   root      336: static const VMStateDescription vmstate_nand = {
                    337:     .name = "nand",
1.1.1.7 ! root      338:     .version_id = 1,
        !           339:     .minimum_version_id = 1,
        !           340:     .minimum_version_id_old = 1,
1.1.1.6   root      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),
1.1.1.7 ! root      353:         VMSTATE_UINT64(addr, NANDFlashState),
1.1.1.6   root      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: 
1.1.1.7 ! root      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: 
1.1       root      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:  */
1.1.1.7 ! root      442: void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
1.1.1.6   root      443:                   uint8_t ce, uint8_t wp, uint8_t gnd)
1.1       root      444: {
1.1.1.7 ! root      445:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      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: 
1.1.1.7 ! root      457: void nand_getpins(DeviceState *dev, int *rb)
1.1       root      458: {
                    459:     *rb = 1;
                    460: }
                    461: 
1.1.1.7 ! root      462: void nand_setio(DeviceState *dev, uint32_t value)
1.1       root      463: {
1.1.1.7 ! root      464:     int i;
        !           465:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      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) {
1.1.1.5   root      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;
1.1       root      509:         s->addrlen ++;
                    510: 
1.1.1.7 ! root      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:         }
1.1       root      546:     }
                    547: 
                    548:     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
1.1.1.7 ! root      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:         }
1.1       root      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)) {
1.1.1.7 ! root      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:             }
1.1       root      561:         }
                    562:     }
                    563: }
                    564: 
1.1.1.7 ! root      565: uint32_t nand_getio(DeviceState *dev)
1.1       root      566: {
                    567:     int offset;
1.1.1.7 ! root      568:     uint32_t x = 0;
        !           569:     NANDFlashState *s = (NANDFlashState *) dev;
1.1       root      570: 
                    571:     /* Allow sequential reading */
                    572:     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
1.1.1.7 ! root      573:         offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
1.1       root      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: 
1.1.1.7 ! root      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;
1.1       root      598: }
                    599: 
1.1.1.7 ! root      600: uint32_t nand_getbuswidth(DeviceState *dev)
1.1       root      601: {
1.1.1.7 ! root      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;
1.1       root      609: 
                    610:     if (nand_flash_ids[chip_id].size == 0) {
1.1.1.3   root      611:         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
1.1       root      612:     }
1.1.1.7 ! root      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);
1.1       root      618:     }
                    619: 
1.1.1.7 ! root      620:     qdev_init_nofail(dev);
        !           621:     return dev;
1.1       root      622: }
                    623: 
1.1.1.7 ! root      624: device_init(nand_create_device)
1.1       root      625: 
                    626: #else
                    627: 
                    628: /* Program a single page */
1.1.1.3   root      629: static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      630: {
1.1.1.7 ! root      631:     uint64_t off, page, sector, soff;
1.1       root      632:     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
                    633:     if (PAGE(s->addr) >= s->pages)
                    634:         return;
                    635: 
                    636:     if (!s->bdrv) {
1.1.1.7 ! root      637:         mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
1.1       root      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) {
1.1.1.7 ! root      644:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      645:             return;
                    646:         }
                    647: 
1.1.1.7 ! root      648:         mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
1.1       root      649:         if (off + s->iolen > PAGE_SIZE) {
                    650:             page = PAGE(s->addr);
1.1.1.7 ! root      651:             mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
1.1       root      652:                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
                    653:         }
                    654: 
                    655:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
1.1.1.7 ! root      656:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      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) {
1.1.1.7 ! root      662:             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      663:             return;
                    664:         }
                    665: 
1.1.1.7 ! root      666:         mem_and(iobuf + soff, s->io, s->iolen);
1.1       root      667: 
                    668:         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
1.1.1.7 ! root      669:             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
1.1       root      670:     }
                    671:     s->offset = 0;
                    672: }
                    673: 
                    674: /* Erase a single block */
1.1.1.3   root      675: static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      676: {
1.1.1.7 ! root      677:     uint64_t i, page, addr;
1.1       root      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)
1.1.1.7 ! root      694:                 printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
1.1       root      695:     } else {
                    696:         addr = PAGE_START(addr);
                    697:         page = addr >> 9;
                    698:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7 ! root      699:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
1.1       root      700:         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
                    701:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7 ! root      702:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
1.1       root      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)
1.1.1.7 ! root      709:                 printf("%s: write error in sector %" PRIu64 "\n",
        !           710:                        __func__, i >> 9);
1.1       root      711: 
                    712:         page = i >> 9;
                    713:         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7 ! root      714:             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
1.1       root      715:         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
                    716:         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
1.1.1.7 ! root      717:             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
1.1       root      718:     }
                    719: }
                    720: 
1.1.1.3   root      721: static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
1.1.1.7 ! root      722:                 uint64_t addr, int offset)
1.1       root      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)
1.1.1.7 ! root      730:                 printf("%s: read error in sector %" PRIu64 "\n",
        !           731:                                 __func__, SECTOR(addr));
1.1       root      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)
1.1.1.7 ! root      739:                 printf("%s: read error in sector %" PRIu64 "\n",
        !           740:                                 __func__, PAGE_START(addr) >> 9);
1.1       root      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: 
1.1.1.3   root      750: static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)
1.1       root      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

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.