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