|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.