|
|
1.1 root 1: /*
2: * CFI parallel flash with AMD command set emulation
1.1.1.3 root 3: *
1.1 root 4: * Copyright (c) 2005 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
1.1.1.5 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19:
20: /*
21: * For now, this code can emulate flashes of 1, 2 or 4 bytes width.
22: * Supported commands/modes are:
23: * - flash read
24: * - flash write
25: * - flash ID read
26: * - sector erase
27: * - chip erase
28: * - unlock bypass command
29: * - CFI queries
30: *
31: * It does not support flash interleaving.
32: * It does not implement boot blocs with reduced size
33: * It does not implement software data protection as found in many real chips
34: * It does not implement erase suspend/resume commands
35: * It does not implement multiple sectors erase
36: */
37:
1.1.1.3 root 38: #include "hw.h"
39: #include "flash.h"
40: #include "qemu-timer.h"
41: #include "block.h"
1.1.1.10! root 42: #include "exec-memory.h"
1.1 root 43:
44: //#define PFLASH_DEBUG
45: #ifdef PFLASH_DEBUG
1.1.1.5 root 46: #define DPRINTF(fmt, ...) \
1.1 root 47: do { \
1.1.1.5 root 48: printf("PFLASH: " fmt , ## __VA_ARGS__); \
1.1 root 49: } while (0)
50: #else
1.1.1.5 root 51: #define DPRINTF(fmt, ...) do { } while (0)
1.1 root 52: #endif
53:
1.1.1.9 root 54: #define PFLASH_LAZY_ROMD_THRESHOLD 42
55:
1.1 root 56: struct pflash_t {
57: BlockDriverState *bs;
1.1.1.3 root 58: target_phys_addr_t base;
59: uint32_t sector_len;
1.1.1.4 root 60: uint32_t chip_len;
61: int mappings;
1.1 root 62: int width;
63: int wcycle; /* if 0, the flash is read normally */
64: int bypass;
65: int ro;
66: uint8_t cmd;
67: uint8_t status;
68: uint16_t ident[4];
1.1.1.4 root 69: uint16_t unlock_addr[2];
1.1 root 70: uint8_t cfi_len;
71: uint8_t cfi_table[0x52];
72: QEMUTimer *timer;
1.1.1.10! root 73: /* The device replicates the flash memory across its memory space. Emulate
! 74: * that by having a container (.mem) filled with an array of aliases
! 75: * (.mem_mappings) pointing to the flash memory (.orig_mem).
! 76: */
! 77: MemoryRegion mem;
! 78: MemoryRegion *mem_mappings; /* array; one per mapping */
! 79: MemoryRegion orig_mem;
1.1.1.4 root 80: int rom_mode;
1.1.1.9 root 81: int read_counter; /* used for lazy switch-back to rom mode */
1.1 root 82: void *storage;
83: };
84:
1.1.1.10! root 85: /*
! 86: * Set up replicated mappings of the same region.
! 87: */
! 88: static void pflash_setup_mappings(pflash_t *pfl)
! 89: {
! 90: unsigned i;
! 91: target_phys_addr_t size = memory_region_size(&pfl->orig_mem);
! 92:
! 93: memory_region_init(&pfl->mem, "pflash", pfl->mappings * size);
! 94: pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
! 95: for (i = 0; i < pfl->mappings; ++i) {
! 96: memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias",
! 97: &pfl->orig_mem, 0, size);
! 98: memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
! 99: }
! 100: }
! 101:
1.1.1.4 root 102: static void pflash_register_memory(pflash_t *pfl, int rom_mode)
103: {
1.1.1.10! root 104: memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
1.1.1.4 root 105: }
106:
1.1 root 107: static void pflash_timer (void *opaque)
108: {
109: pflash_t *pfl = opaque;
110:
111: DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
112: /* Reset flash */
113: pfl->status ^= 0x80;
114: if (pfl->bypass) {
115: pfl->wcycle = 2;
116: } else {
1.1.1.4 root 117: pflash_register_memory(pfl, 1);
1.1 root 118: pfl->wcycle = 0;
119: }
120: pfl->cmd = 0;
121: }
122:
1.1.1.7 root 123: static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset,
124: int width, int be)
1.1 root 125: {
1.1.1.7 root 126: target_phys_addr_t boff;
1.1 root 127: uint32_t ret;
128: uint8_t *p;
129:
1.1.1.7 root 130: DPRINTF("%s: offset " TARGET_FMT_plx "\n", __func__, offset);
1.1 root 131: ret = -1;
1.1.1.9 root 132: /* Lazy reset to ROMD mode after a certain amount of read accesses */
133: if (!pfl->rom_mode && pfl->wcycle == 0 &&
134: ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) {
135: pflash_register_memory(pfl, 1);
1.1.1.4 root 136: }
137: offset &= pfl->chip_len - 1;
1.1 root 138: boff = offset & 0xFF;
139: if (pfl->width == 2)
140: boff = boff >> 1;
141: else if (pfl->width == 4)
142: boff = boff >> 2;
143: switch (pfl->cmd) {
144: default:
145: /* This should never happen : reset state & treat it as a read*/
146: DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
147: pfl->wcycle = 0;
148: pfl->cmd = 0;
149: case 0x80:
150: /* We accept reads during second unlock sequence... */
151: case 0x00:
152: flash_read:
153: /* Flash area read */
154: p = pfl->storage;
155: switch (width) {
156: case 1:
157: ret = p[offset];
158: // DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret);
159: break;
160: case 2:
1.1.1.7 root 161: if (be) {
162: ret = p[offset] << 8;
163: ret |= p[offset + 1];
164: } else {
165: ret = p[offset];
166: ret |= p[offset + 1] << 8;
167: }
1.1 root 168: // DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret);
169: break;
170: case 4:
1.1.1.7 root 171: if (be) {
172: ret = p[offset] << 24;
173: ret |= p[offset + 1] << 16;
174: ret |= p[offset + 2] << 8;
175: ret |= p[offset + 3];
176: } else {
177: ret = p[offset];
178: ret |= p[offset + 1] << 8;
179: ret |= p[offset + 2] << 16;
180: ret |= p[offset + 3] << 24;
181: }
1.1 root 182: // DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret);
183: break;
184: }
185: break;
186: case 0x90:
187: /* flash ID read */
188: switch (boff) {
189: case 0x00:
190: case 0x01:
191: ret = pfl->ident[boff & 0x01];
192: break;
193: case 0x02:
194: ret = 0x00; /* Pretend all sectors are unprotected */
195: break;
196: case 0x0E:
197: case 0x0F:
198: if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
199: goto flash_read;
200: ret = pfl->ident[2 + (boff & 0x01)];
201: break;
202: default:
203: goto flash_read;
204: }
1.1.1.9 root 205: DPRINTF("%s: ID " TARGET_FMT_plx " %x\n", __func__, boff, ret);
1.1 root 206: break;
207: case 0xA0:
208: case 0x10:
209: case 0x30:
210: /* Status register read */
211: ret = pfl->status;
212: DPRINTF("%s: status %x\n", __func__, ret);
213: /* Toggle bit 6 */
214: pfl->status ^= 0x40;
215: break;
216: case 0x98:
217: /* CFI query mode */
218: if (boff > pfl->cfi_len)
219: ret = 0;
220: else
221: ret = pfl->cfi_table[boff];
222: break;
223: }
224:
225: return ret;
226: }
227:
228: /* update flash content on disk */
1.1.1.3 root 229: static void pflash_update(pflash_t *pfl, int offset,
1.1 root 230: int size)
231: {
232: int offset_end;
233: if (pfl->bs) {
234: offset_end = offset + size;
235: /* round to sectors */
236: offset = offset >> 9;
237: offset_end = (offset_end + 511) >> 9;
1.1.1.3 root 238: bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
1.1 root 239: offset_end - offset);
240: }
241: }
242:
1.1.1.7 root 243: static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
244: uint32_t value, int width, int be)
1.1 root 245: {
1.1.1.7 root 246: target_phys_addr_t boff;
1.1 root 247: uint8_t *p;
248: uint8_t cmd;
249:
250: cmd = value;
251: if (pfl->cmd != 0xA0 && cmd == 0xF0) {
1.1.1.3 root 252: #if 0
1.1 root 253: DPRINTF("%s: flash reset asked (%02x %02x)\n",
254: __func__, pfl->cmd, cmd);
1.1.1.3 root 255: #endif
1.1 root 256: goto reset_flash;
257: }
1.1.1.7 root 258: DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d %d\n", __func__,
1.1.1.3 root 259: offset, value, width, pfl->wcycle);
1.1.1.4 root 260: offset &= pfl->chip_len - 1;
1.1.1.3 root 261:
1.1.1.7 root 262: DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d\n", __func__,
1.1.1.3 root 263: offset, value, width);
1.1 root 264: boff = offset & (pfl->sector_len - 1);
265: if (pfl->width == 2)
266: boff = boff >> 1;
267: else if (pfl->width == 4)
268: boff = boff >> 2;
269: switch (pfl->wcycle) {
270: case 0:
1.1.1.4 root 271: /* Set the device in I/O access mode if required */
272: if (pfl->rom_mode)
273: pflash_register_memory(pfl, 0);
1.1.1.9 root 274: pfl->read_counter = 0;
1.1 root 275: /* We're in read mode */
276: check_unlock0:
277: if (boff == 0x55 && cmd == 0x98) {
278: enter_CFI_mode:
279: /* Enter CFI query mode */
280: pfl->wcycle = 7;
281: pfl->cmd = 0x98;
282: return;
283: }
1.1.1.4 root 284: if (boff != pfl->unlock_addr[0] || cmd != 0xAA) {
1.1.1.7 root 285: DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n",
1.1.1.4 root 286: __func__, boff, cmd, pfl->unlock_addr[0]);
1.1 root 287: goto reset_flash;
288: }
289: DPRINTF("%s: unlock sequence started\n", __func__);
290: break;
291: case 1:
292: /* We started an unlock sequence */
293: check_unlock1:
1.1.1.4 root 294: if (boff != pfl->unlock_addr[1] || cmd != 0x55) {
1.1.1.7 root 295: DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__,
1.1.1.3 root 296: boff, cmd);
1.1 root 297: goto reset_flash;
298: }
299: DPRINTF("%s: unlock sequence done\n", __func__);
300: break;
301: case 2:
302: /* We finished an unlock sequence */
1.1.1.4 root 303: if (!pfl->bypass && boff != pfl->unlock_addr[0]) {
1.1.1.7 root 304: DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__,
1.1.1.3 root 305: boff, cmd);
1.1 root 306: goto reset_flash;
307: }
308: switch (cmd) {
309: case 0x20:
310: pfl->bypass = 1;
311: goto do_bypass;
312: case 0x80:
313: case 0x90:
314: case 0xA0:
315: pfl->cmd = cmd;
316: DPRINTF("%s: starting command %02x\n", __func__, cmd);
317: break;
318: default:
319: DPRINTF("%s: unknown command %02x\n", __func__, cmd);
320: goto reset_flash;
321: }
322: break;
323: case 3:
324: switch (pfl->cmd) {
325: case 0x80:
326: /* We need another unlock sequence */
327: goto check_unlock0;
328: case 0xA0:
1.1.1.7 root 329: DPRINTF("%s: write data offset " TARGET_FMT_plx " %08x %d\n",
1.1 root 330: __func__, offset, value, width);
331: p = pfl->storage;
332: switch (width) {
333: case 1:
334: p[offset] &= value;
335: pflash_update(pfl, offset, 1);
336: break;
337: case 2:
1.1.1.7 root 338: if (be) {
339: p[offset] &= value >> 8;
340: p[offset + 1] &= value;
341: } else {
342: p[offset] &= value;
343: p[offset + 1] &= value >> 8;
344: }
1.1 root 345: pflash_update(pfl, offset, 2);
346: break;
347: case 4:
1.1.1.7 root 348: if (be) {
349: p[offset] &= value >> 24;
350: p[offset + 1] &= value >> 16;
351: p[offset + 2] &= value >> 8;
352: p[offset + 3] &= value;
353: } else {
354: p[offset] &= value;
355: p[offset + 1] &= value >> 8;
356: p[offset + 2] &= value >> 16;
357: p[offset + 3] &= value >> 24;
358: }
1.1 root 359: pflash_update(pfl, offset, 4);
360: break;
361: }
362: pfl->status = 0x00 | ~(value & 0x80);
363: /* Let's pretend write is immediate */
364: if (pfl->bypass)
365: goto do_bypass;
366: goto reset_flash;
367: case 0x90:
368: if (pfl->bypass && cmd == 0x00) {
369: /* Unlock bypass reset */
370: goto reset_flash;
371: }
372: /* We can enter CFI query mode from autoselect mode */
373: if (boff == 0x55 && cmd == 0x98)
374: goto enter_CFI_mode;
375: /* No break here */
376: default:
377: DPRINTF("%s: invalid write for command %02x\n",
378: __func__, pfl->cmd);
379: goto reset_flash;
380: }
381: case 4:
382: switch (pfl->cmd) {
383: case 0xA0:
1.1.1.9 root 384: /* Ignore writes while flash data write is occurring */
1.1 root 385: /* As we suppose write is immediate, this should never happen */
386: return;
387: case 0x80:
388: goto check_unlock1;
389: default:
390: /* Should never happen */
391: DPRINTF("%s: invalid command state %02x (wc 4)\n",
392: __func__, pfl->cmd);
393: goto reset_flash;
394: }
395: break;
396: case 5:
397: switch (cmd) {
398: case 0x10:
1.1.1.4 root 399: if (boff != pfl->unlock_addr[0]) {
1.1.1.7 root 400: DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n",
1.1 root 401: __func__, offset);
402: goto reset_flash;
403: }
404: /* Chip erase */
405: DPRINTF("%s: start chip erase\n", __func__);
1.1.1.4 root 406: memset(pfl->storage, 0xFF, pfl->chip_len);
1.1 root 407: pfl->status = 0x00;
1.1.1.4 root 408: pflash_update(pfl, 0, pfl->chip_len);
1.1 root 409: /* Let's wait 5 seconds before chip erase is done */
1.1.1.3 root 410: qemu_mod_timer(pfl->timer,
1.1.1.9 root 411: qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 5));
1.1 root 412: break;
413: case 0x30:
414: /* Sector erase */
415: p = pfl->storage;
416: offset &= ~(pfl->sector_len - 1);
1.1.1.7 root 417: DPRINTF("%s: start sector erase at " TARGET_FMT_plx "\n", __func__,
1.1.1.3 root 418: offset);
1.1 root 419: memset(p + offset, 0xFF, pfl->sector_len);
420: pflash_update(pfl, offset, pfl->sector_len);
421: pfl->status = 0x00;
422: /* Let's wait 1/2 second before sector erase is done */
1.1.1.3 root 423: qemu_mod_timer(pfl->timer,
1.1.1.9 root 424: qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 2));
1.1 root 425: break;
426: default:
427: DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
428: goto reset_flash;
429: }
430: pfl->cmd = cmd;
431: break;
432: case 6:
433: switch (pfl->cmd) {
434: case 0x10:
435: /* Ignore writes during chip erase */
436: return;
437: case 0x30:
438: /* Ignore writes during sector erase */
439: return;
440: default:
441: /* Should never happen */
442: DPRINTF("%s: invalid command state %02x (wc 6)\n",
443: __func__, pfl->cmd);
444: goto reset_flash;
445: }
446: break;
447: case 7: /* Special value for CFI queries */
448: DPRINTF("%s: invalid write in CFI query mode\n", __func__);
449: goto reset_flash;
450: default:
451: /* Should never happen */
452: DPRINTF("%s: invalid write state (wc 7)\n", __func__);
453: goto reset_flash;
454: }
455: pfl->wcycle++;
456:
457: return;
458:
459: /* Reset flash */
460: reset_flash:
461: pfl->bypass = 0;
462: pfl->wcycle = 0;
463: pfl->cmd = 0;
464: return;
465:
466: do_bypass:
467: pfl->wcycle = 2;
468: pfl->cmd = 0;
469: return;
470: }
471:
472:
1.1.1.7 root 473: static uint32_t pflash_readb_be(void *opaque, target_phys_addr_t addr)
474: {
475: return pflash_read(opaque, addr, 1, 1);
476: }
477:
478: static uint32_t pflash_readb_le(void *opaque, target_phys_addr_t addr)
1.1 root 479: {
1.1.1.7 root 480: return pflash_read(opaque, addr, 1, 0);
1.1 root 481: }
482:
1.1.1.7 root 483: static uint32_t pflash_readw_be(void *opaque, target_phys_addr_t addr)
1.1 root 484: {
485: pflash_t *pfl = opaque;
486:
1.1.1.7 root 487: return pflash_read(pfl, addr, 2, 1);
1.1 root 488: }
489:
1.1.1.7 root 490: static uint32_t pflash_readw_le(void *opaque, target_phys_addr_t addr)
1.1 root 491: {
492: pflash_t *pfl = opaque;
493:
1.1.1.7 root 494: return pflash_read(pfl, addr, 2, 0);
1.1 root 495: }
496:
1.1.1.7 root 497: static uint32_t pflash_readl_be(void *opaque, target_phys_addr_t addr)
1.1 root 498: {
1.1.1.7 root 499: pflash_t *pfl = opaque;
500:
501: return pflash_read(pfl, addr, 4, 1);
1.1 root 502: }
503:
1.1.1.7 root 504: static uint32_t pflash_readl_le(void *opaque, target_phys_addr_t addr)
1.1 root 505: {
506: pflash_t *pfl = opaque;
507:
1.1.1.7 root 508: return pflash_read(pfl, addr, 4, 0);
509: }
510:
511: static void pflash_writeb_be(void *opaque, target_phys_addr_t addr,
512: uint32_t value)
513: {
514: pflash_write(opaque, addr, value, 1, 1);
1.1 root 515: }
516:
1.1.1.7 root 517: static void pflash_writeb_le(void *opaque, target_phys_addr_t addr,
518: uint32_t value)
519: {
520: pflash_write(opaque, addr, value, 1, 0);
521: }
522:
523: static void pflash_writew_be(void *opaque, target_phys_addr_t addr,
524: uint32_t value)
525: {
526: pflash_t *pfl = opaque;
527:
528: pflash_write(pfl, addr, value, 2, 1);
529: }
530:
531: static void pflash_writew_le(void *opaque, target_phys_addr_t addr,
532: uint32_t value)
1.1 root 533: {
534: pflash_t *pfl = opaque;
535:
1.1.1.7 root 536: pflash_write(pfl, addr, value, 2, 0);
1.1 root 537: }
538:
1.1.1.7 root 539: static void pflash_writel_be(void *opaque, target_phys_addr_t addr,
540: uint32_t value)
541: {
542: pflash_t *pfl = opaque;
543:
544: pflash_write(pfl, addr, value, 4, 1);
545: }
546:
547: static void pflash_writel_le(void *opaque, target_phys_addr_t addr,
548: uint32_t value)
549: {
550: pflash_t *pfl = opaque;
551:
552: pflash_write(pfl, addr, value, 4, 0);
553: }
554:
1.1.1.10! root 555: static const MemoryRegionOps pflash_cfi02_ops_be = {
! 556: .old_mmio = {
! 557: .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
! 558: .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
! 559: },
! 560: .endianness = DEVICE_NATIVE_ENDIAN,
1.1.1.7 root 561: };
562:
1.1.1.10! root 563: static const MemoryRegionOps pflash_cfi02_ops_le = {
! 564: .old_mmio = {
! 565: .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
! 566: .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
! 567: },
! 568: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 569: };
570:
571: /* Count trailing zeroes of a 32 bits quantity */
572: static int ctz32 (uint32_t n)
573: {
574: int ret;
575:
576: ret = 0;
577: if (!(n & 0xFFFF)) {
578: ret += 16;
579: n = n >> 16;
580: }
581: if (!(n & 0xFF)) {
582: ret += 8;
583: n = n >> 8;
584: }
585: if (!(n & 0xF)) {
586: ret += 4;
587: n = n >> 4;
588: }
589: if (!(n & 0x3)) {
590: ret += 2;
591: n = n >> 2;
592: }
593: if (!(n & 0x1)) {
594: ret++;
1.1.1.7 root 595: #if 0 /* This is not necessary as n is never 0 */
1.1 root 596: n = n >> 1;
1.1.1.7 root 597: #endif
1.1 root 598: }
599: #if 0 /* This is not necessary as n is never 0 */
600: if (!n)
601: ret++;
602: #endif
603:
604: return ret;
605: }
606:
1.1.1.10! root 607: pflash_t *pflash_cfi02_register(target_phys_addr_t base,
! 608: DeviceState *qdev, const char *name,
! 609: target_phys_addr_t size,
1.1.1.3 root 610: BlockDriverState *bs, uint32_t sector_len,
1.1.1.4 root 611: int nb_blocs, int nb_mappings, int width,
1.1.1.3 root 612: uint16_t id0, uint16_t id1,
1.1.1.4 root 613: uint16_t id2, uint16_t id3,
1.1.1.7 root 614: uint16_t unlock_addr0, uint16_t unlock_addr1,
615: int be)
1.1 root 616: {
617: pflash_t *pfl;
1.1.1.4 root 618: int32_t chip_len;
1.1.1.6 root 619: int ret;
1.1 root 620:
1.1.1.4 root 621: chip_len = sector_len * nb_blocs;
1.1 root 622: /* XXX: to be fixed */
1.1.1.3 root 623: #if 0
1.1 root 624: if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
625: total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
626: return NULL;
1.1.1.3 root 627: #endif
1.1.1.10! root 628: pfl = g_malloc0(sizeof(pflash_t));
! 629: memory_region_init_rom_device(
! 630: &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl,
! 631: qdev, name, size);
! 632: pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
1.1.1.4 root 633: pfl->base = base;
634: pfl->chip_len = chip_len;
635: pfl->mappings = nb_mappings;
1.1 root 636: pfl->bs = bs;
637: if (pfl->bs) {
638: /* read the initial flash content */
1.1.1.6 root 639: ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
640: if (ret < 0) {
1.1.1.10! root 641: g_free(pfl);
1.1.1.6 root 642: return NULL;
643: }
1.1.1.10! root 644: bdrv_attach_dev_nofail(pfl->bs, pfl);
1.1 root 645: }
1.1.1.10! root 646: pflash_setup_mappings(pfl);
! 647: pfl->rom_mode = 1;
! 648: memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
1.1 root 649: #if 0 /* XXX: there should be a bit to set up read-only,
650: * the same way the hardware does (with WP pin).
651: */
652: pfl->ro = 1;
653: #else
654: pfl->ro = 0;
655: #endif
1.1.1.9 root 656: pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
1.1 root 657: pfl->sector_len = sector_len;
658: pfl->width = width;
659: pfl->wcycle = 0;
660: pfl->cmd = 0;
661: pfl->status = 0;
662: pfl->ident[0] = id0;
663: pfl->ident[1] = id1;
664: pfl->ident[2] = id2;
665: pfl->ident[3] = id3;
1.1.1.4 root 666: pfl->unlock_addr[0] = unlock_addr0;
667: pfl->unlock_addr[1] = unlock_addr1;
1.1 root 668: /* Hardcoded CFI table (mostly from SG29 Spansion flash) */
669: pfl->cfi_len = 0x52;
670: /* Standard "QRY" string */
671: pfl->cfi_table[0x10] = 'Q';
672: pfl->cfi_table[0x11] = 'R';
673: pfl->cfi_table[0x12] = 'Y';
674: /* Command set (AMD/Fujitsu) */
675: pfl->cfi_table[0x13] = 0x02;
676: pfl->cfi_table[0x14] = 0x00;
1.1.1.4 root 677: /* Primary extended table address */
678: pfl->cfi_table[0x15] = 0x31;
1.1 root 679: pfl->cfi_table[0x16] = 0x00;
680: /* Alternate command set (none) */
681: pfl->cfi_table[0x17] = 0x00;
682: pfl->cfi_table[0x18] = 0x00;
683: /* Alternate extended table (none) */
684: pfl->cfi_table[0x19] = 0x00;
685: pfl->cfi_table[0x1A] = 0x00;
686: /* Vcc min */
687: pfl->cfi_table[0x1B] = 0x27;
688: /* Vcc max */
689: pfl->cfi_table[0x1C] = 0x36;
690: /* Vpp min (no Vpp pin) */
691: pfl->cfi_table[0x1D] = 0x00;
692: /* Vpp max (no Vpp pin) */
693: pfl->cfi_table[0x1E] = 0x00;
694: /* Reserved */
695: pfl->cfi_table[0x1F] = 0x07;
1.1.1.4 root 696: /* Timeout for min size buffer write (NA) */
697: pfl->cfi_table[0x20] = 0x00;
1.1 root 698: /* Typical timeout for block erase (512 ms) */
699: pfl->cfi_table[0x21] = 0x09;
700: /* Typical timeout for full chip erase (4096 ms) */
701: pfl->cfi_table[0x22] = 0x0C;
702: /* Reserved */
703: pfl->cfi_table[0x23] = 0x01;
1.1.1.4 root 704: /* Max timeout for buffer write (NA) */
705: pfl->cfi_table[0x24] = 0x00;
1.1 root 706: /* Max timeout for block erase */
707: pfl->cfi_table[0x25] = 0x0A;
708: /* Max timeout for chip erase */
709: pfl->cfi_table[0x26] = 0x0D;
710: /* Device size */
1.1.1.4 root 711: pfl->cfi_table[0x27] = ctz32(chip_len);
1.1 root 712: /* Flash device interface (8 & 16 bits) */
713: pfl->cfi_table[0x28] = 0x02;
714: pfl->cfi_table[0x29] = 0x00;
715: /* Max number of bytes in multi-bytes write */
1.1.1.3 root 716: /* XXX: disable buffered write as it's not supported */
717: // pfl->cfi_table[0x2A] = 0x05;
718: pfl->cfi_table[0x2A] = 0x00;
1.1 root 719: pfl->cfi_table[0x2B] = 0x00;
720: /* Number of erase block regions (uniform) */
721: pfl->cfi_table[0x2C] = 0x01;
722: /* Erase block region 1 */
723: pfl->cfi_table[0x2D] = nb_blocs - 1;
724: pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
725: pfl->cfi_table[0x2F] = sector_len >> 8;
726: pfl->cfi_table[0x30] = sector_len >> 16;
727:
1.1.1.4 root 728: /* Extended */
729: pfl->cfi_table[0x31] = 'P';
730: pfl->cfi_table[0x32] = 'R';
731: pfl->cfi_table[0x33] = 'I';
732:
733: pfl->cfi_table[0x34] = '1';
734: pfl->cfi_table[0x35] = '0';
735:
736: pfl->cfi_table[0x36] = 0x00;
737: pfl->cfi_table[0x37] = 0x00;
738: pfl->cfi_table[0x38] = 0x00;
739: pfl->cfi_table[0x39] = 0x00;
740:
741: pfl->cfi_table[0x3a] = 0x00;
742:
743: pfl->cfi_table[0x3b] = 0x00;
744: pfl->cfi_table[0x3c] = 0x00;
745:
1.1 root 746: return pfl;
747: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.