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