1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include "qemu/osdep.h"
40#include "hw/hw.h"
41#include "hw/block/flash.h"
42#include "sysemu/block-backend.h"
43#include "qapi/error.h"
44#include "qemu/timer.h"
45#include "qemu/bitops.h"
46#include "exec/address-spaces.h"
47#include "qemu/host-utils.h"
48#include "qemu/log.h"
49#include "hw/sysbus.h"
50#include "sysemu/sysemu.h"
51
52#define PFLASH_BUG(fmt, ...) \
53do { \
54 fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
55 exit(1); \
56} while(0)
57
58
59#ifdef PFLASH_DEBUG
60#define DPRINTF(fmt, ...) \
61do { \
62 fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \
63} while (0)
64#else
65#define DPRINTF(fmt, ...) do { } while (0)
66#endif
67
68#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
69
70#define PFLASH_BE 0
71#define PFLASH_SECURE 1
72
73struct pflash_t {
74
75 SysBusDevice parent_obj;
76
77
78 BlockBackend *blk;
79 uint32_t nb_blocs;
80 uint64_t sector_len;
81 uint8_t bank_width;
82 uint8_t device_width;
83 uint8_t max_device_width;
84 uint32_t features;
85 uint8_t wcycle;
86 int ro;
87 uint8_t cmd;
88 uint8_t status;
89 uint16_t ident0;
90 uint16_t ident1;
91 uint16_t ident2;
92 uint16_t ident3;
93 uint8_t cfi_len;
94 uint8_t cfi_table[0x52];
95 uint64_t counter;
96 unsigned int writeblock_size;
97 QEMUTimer *timer;
98 MemoryRegion mem;
99 char *name;
100 void *storage;
101 VMChangeStateEntry *vmstate;
102 bool old_multiple_chip_handling;
103};
104
105static int pflash_post_load(void *opaque, int version_id);
106
107static const VMStateDescription vmstate_pflash = {
108 .name = "pflash_cfi01",
109 .version_id = 1,
110 .minimum_version_id = 1,
111 .post_load = pflash_post_load,
112 .fields = (VMStateField[]) {
113 VMSTATE_UINT8(wcycle, pflash_t),
114 VMSTATE_UINT8(cmd, pflash_t),
115 VMSTATE_UINT8(status, pflash_t),
116 VMSTATE_UINT64(counter, pflash_t),
117 VMSTATE_END_OF_LIST()
118 }
119};
120
121static void pflash_timer (void *opaque)
122{
123 pflash_t *pfl = opaque;
124
125 DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
126
127 pfl->status ^= 0x80;
128 memory_region_rom_device_set_romd(&pfl->mem, true);
129 pfl->wcycle = 0;
130 pfl->cmd = 0;
131}
132
133
134
135
136
137static uint32_t pflash_cfi_query(pflash_t *pfl, hwaddr offset)
138{
139 int i;
140 uint32_t resp = 0;
141 hwaddr boff;
142
143
144
145
146
147
148
149
150
151
152
153 boff = offset >> (ctz32(pfl->bank_width) +
154 ctz32(pfl->max_device_width) - ctz32(pfl->device_width));
155
156 if (boff > pfl->cfi_len) {
157 return 0;
158 }
159
160
161
162
163
164 resp = pfl->cfi_table[boff];
165 if (pfl->device_width != pfl->max_device_width) {
166
167
168
169 if (pfl->device_width != 1 || pfl->bank_width > 4) {
170 DPRINTF("%s: Unsupported device configuration: "
171 "device_width=%d, max_device_width=%d\n",
172 __func__, pfl->device_width,
173 pfl->max_device_width);
174 return 0;
175 }
176
177
178
179 for (i = 1; i < pfl->max_device_width; i++) {
180 resp = deposit32(resp, 8 * i, 8, pfl->cfi_table[boff]);
181 }
182 }
183
184 if (pfl->device_width < pfl->bank_width) {
185 for (i = pfl->device_width;
186 i < pfl->bank_width; i += pfl->device_width) {
187 resp = deposit32(resp, 8 * i, 8 * pfl->device_width, resp);
188 }
189 }
190
191 return resp;
192}
193
194
195
196
197static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
198{
199 int i;
200 uint32_t resp;
201 hwaddr boff;
202
203
204
205
206
207
208
209
210
211
212
213 boff = offset >> (ctz32(pfl->bank_width) +
214 ctz32(pfl->max_device_width) - ctz32(pfl->device_width));
215
216
217
218
219
220 switch (boff & 0xFF) {
221 case 0:
222 resp = pfl->ident0;
223 DPRINTF("%s: Manufacturer Code %04x\n", __func__, resp);
224 break;
225 case 1:
226 resp = pfl->ident1;
227 DPRINTF("%s: Device ID Code %04x\n", __func__, resp);
228 break;
229 default:
230 DPRINTF("%s: Read Device Information offset=%x\n", __func__,
231 (unsigned)offset);
232 return 0;
233 break;
234 }
235
236 if (pfl->device_width < pfl->bank_width) {
237 for (i = pfl->device_width;
238 i < pfl->bank_width; i += pfl->device_width) {
239 resp = deposit32(resp, 8 * i, 8 * pfl->device_width, resp);
240 }
241 }
242
243 return resp;
244}
245
246static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
247 int width, int be)
248{
249 uint8_t *p;
250 uint32_t ret;
251
252 p = pfl->storage;
253 switch (width) {
254 case 1:
255 ret = p[offset];
256 DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
257 __func__, offset, ret);
258 break;
259 case 2:
260 if (be) {
261 ret = p[offset] << 8;
262 ret |= p[offset + 1];
263 } else {
264 ret = p[offset];
265 ret |= p[offset + 1] << 8;
266 }
267 DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
268 __func__, offset, ret);
269 break;
270 case 4:
271 if (be) {
272 ret = p[offset] << 24;
273 ret |= p[offset + 1] << 16;
274 ret |= p[offset + 2] << 8;
275 ret |= p[offset + 3];
276 } else {
277 ret = p[offset];
278 ret |= p[offset + 1] << 8;
279 ret |= p[offset + 2] << 16;
280 ret |= p[offset + 3] << 24;
281 }
282 DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
283 __func__, offset, ret);
284 break;
285 default:
286 DPRINTF("BUG in %s\n", __func__);
287 abort();
288 }
289 return ret;
290}
291
292static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
293 int width, int be)
294{
295 hwaddr boff;
296 uint32_t ret;
297
298 ret = -1;
299
300#if 0
301 DPRINTF("%s: reading offset " TARGET_FMT_plx " under cmd %02x width %d\n",
302 __func__, offset, pfl->cmd, width);
303#endif
304 switch (pfl->cmd) {
305 default:
306
307 DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
308 pfl->wcycle = 0;
309 pfl->cmd = 0;
310
311 case 0x00:
312
313 ret = pflash_data_read(pfl, offset, width, be);
314 break;
315 case 0x10:
316 case 0x20:
317 case 0x28:
318 case 0x40:
319 case 0x50:
320 case 0x60:
321 case 0x70:
322 case 0xe8:
323
324
325
326 ret = pfl->status;
327 if (pfl->device_width && width > pfl->device_width) {
328 int shift = pfl->device_width * 8;
329 while (shift + pfl->device_width * 8 <= width * 8) {
330 ret |= pfl->status << shift;
331 shift += pfl->device_width * 8;
332 }
333 } else if (!pfl->device_width && width > 2) {
334
335
336
337 ret |= pfl->status << 16;
338 }
339 DPRINTF("%s: status %x\n", __func__, ret);
340 break;
341 case 0x90:
342 if (!pfl->device_width) {
343
344 boff = offset & 0xFF;
345 if (pfl->bank_width == 2) {
346 boff = boff >> 1;
347 } else if (pfl->bank_width == 4) {
348 boff = boff >> 2;
349 }
350
351 switch (boff) {
352 case 0:
353 ret = pfl->ident0 << 8 | pfl->ident1;
354 DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
355 break;
356 case 1:
357 ret = pfl->ident2 << 8 | pfl->ident3;
358 DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
359 break;
360 default:
361 DPRINTF("%s: Read Device Information boff=%x\n", __func__,
362 (unsigned)boff);
363 ret = 0;
364 break;
365 }
366 } else {
367
368
369
370 int i;
371 for (i = 0; i < width; i += pfl->bank_width) {
372 ret = deposit32(ret, i * 8, pfl->bank_width * 8,
373 pflash_devid_query(pfl,
374 offset + i * pfl->bank_width));
375 }
376 }
377 break;
378 case 0x98:
379 if (!pfl->device_width) {
380
381 boff = offset & 0xFF;
382 if (pfl->bank_width == 2) {
383 boff = boff >> 1;
384 } else if (pfl->bank_width == 4) {
385 boff = boff >> 2;
386 }
387
388 if (boff > pfl->cfi_len) {
389 ret = 0;
390 } else {
391 ret = pfl->cfi_table[boff];
392 }
393 } else {
394
395
396
397 int i;
398 for (i = 0; i < width; i += pfl->bank_width) {
399 ret = deposit32(ret, i * 8, pfl->bank_width * 8,
400 pflash_cfi_query(pfl,
401 offset + i * pfl->bank_width));
402 }
403 }
404
405 break;
406 }
407 return ret;
408}
409
410
411static void pflash_update(pflash_t *pfl, int offset,
412 int size)
413{
414 int offset_end;
415 if (pfl->blk) {
416 offset_end = offset + size;
417
418 offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
419 offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
420 blk_pwrite(pfl->blk, offset, pfl->storage + offset,
421 offset_end - offset, 0);
422 }
423}
424
425static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
426 uint32_t value, int width, int be)
427{
428 uint8_t *p = pfl->storage;
429
430 DPRINTF("%s: block write offset " TARGET_FMT_plx
431 " value %x counter %016" PRIx64 "\n",
432 __func__, offset, value, pfl->counter);
433 switch (width) {
434 case 1:
435 p[offset] = value;
436 break;
437 case 2:
438 if (be) {
439 p[offset] = value >> 8;
440 p[offset + 1] = value;
441 } else {
442 p[offset] = value;
443 p[offset + 1] = value >> 8;
444 }
445 break;
446 case 4:
447 if (be) {
448 p[offset] = value >> 24;
449 p[offset + 1] = value >> 16;
450 p[offset + 2] = value >> 8;
451 p[offset + 3] = value;
452 } else {
453 p[offset] = value;
454 p[offset + 1] = value >> 8;
455 p[offset + 2] = value >> 16;
456 p[offset + 3] = value >> 24;
457 }
458 break;
459 }
460
461}
462
463static void pflash_write(pflash_t *pfl, hwaddr offset,
464 uint32_t value, int width, int be)
465{
466 uint8_t *p;
467 uint8_t cmd;
468
469 cmd = value;
470
471 DPRINTF("%s: writing offset " TARGET_FMT_plx " value %08x width %d wcycle 0x%x\n",
472 __func__, offset, value, width, pfl->wcycle);
473
474 if (!pfl->wcycle) {
475
476 memory_region_rom_device_set_romd(&pfl->mem, false);
477 }
478
479 switch (pfl->wcycle) {
480 case 0:
481
482 switch (cmd) {
483 case 0x00:
484 goto reset_flash;
485 case 0x10:
486 case 0x40:
487 DPRINTF("%s: Single Byte Program\n", __func__);
488 break;
489 case 0x20:
490 p = pfl->storage;
491 offset &= ~(pfl->sector_len - 1);
492
493 DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes %x\n",
494 __func__, offset, (unsigned)pfl->sector_len);
495
496 if (!pfl->ro) {
497 memset(p + offset, 0xff, pfl->sector_len);
498 pflash_update(pfl, offset, pfl->sector_len);
499 } else {
500 pfl->status |= 0x20;
501 }
502 pfl->status |= 0x80;
503 break;
504 case 0x50:
505 DPRINTF("%s: Clear status bits\n", __func__);
506 pfl->status = 0x0;
507 goto reset_flash;
508 case 0x60:
509 DPRINTF("%s: Block unlock\n", __func__);
510 break;
511 case 0x70:
512 DPRINTF("%s: Read status register\n", __func__);
513 pfl->cmd = cmd;
514 return;
515 case 0x90:
516 DPRINTF("%s: Read Device information\n", __func__);
517 pfl->cmd = cmd;
518 return;
519 case 0x98:
520 DPRINTF("%s: CFI query\n", __func__);
521 break;
522 case 0xe8:
523 DPRINTF("%s: Write to buffer\n", __func__);
524 pfl->status |= 0x80;
525 break;
526 case 0xf0:
527 DPRINTF("%s: Probe for AMD flash\n", __func__);
528 goto reset_flash;
529 case 0xff:
530 DPRINTF("%s: Read array mode\n", __func__);
531 goto reset_flash;
532 default:
533 goto error_flash;
534 }
535 pfl->wcycle++;
536 pfl->cmd = cmd;
537 break;
538 case 1:
539 switch (pfl->cmd) {
540 case 0x10:
541 case 0x40:
542 DPRINTF("%s: Single Byte Program\n", __func__);
543 if (!pfl->ro) {
544 pflash_data_write(pfl, offset, value, width, be);
545 pflash_update(pfl, offset, width);
546 } else {
547 pfl->status |= 0x10;
548 }
549 pfl->status |= 0x80;
550 pfl->wcycle = 0;
551 break;
552 case 0x20:
553 case 0x28:
554 if (cmd == 0xd0) {
555 pfl->wcycle = 0;
556 pfl->status |= 0x80;
557 } else if (cmd == 0xff) {
558 goto reset_flash;
559 } else
560 goto error_flash;
561
562 break;
563 case 0xe8:
564
565
566
567 if (pfl->device_width) {
568 value = extract32(value, 0, pfl->device_width * 8);
569 } else {
570 value = extract32(value, 0, pfl->bank_width * 8);
571 }
572 DPRINTF("%s: block write of %x bytes\n", __func__, value);
573 pfl->counter = value;
574 pfl->wcycle++;
575 break;
576 case 0x60:
577 if (cmd == 0xd0) {
578 pfl->wcycle = 0;
579 pfl->status |= 0x80;
580 } else if (cmd == 0x01) {
581 pfl->wcycle = 0;
582 pfl->status |= 0x80;
583 } else if (cmd == 0xff) {
584 goto reset_flash;
585 } else {
586 DPRINTF("%s: Unknown (un)locking command\n", __func__);
587 goto reset_flash;
588 }
589 break;
590 case 0x98:
591 if (cmd == 0xff) {
592 goto reset_flash;
593 } else {
594 DPRINTF("%s: leaving query mode\n", __func__);
595 }
596 break;
597 default:
598 goto error_flash;
599 }
600 break;
601 case 2:
602 switch (pfl->cmd) {
603 case 0xe8:
604 if (!pfl->ro) {
605 pflash_data_write(pfl, offset, value, width, be);
606 } else {
607 pfl->status |= 0x10;
608 }
609
610 pfl->status |= 0x80;
611
612 if (!pfl->counter) {
613 hwaddr mask = pfl->writeblock_size - 1;
614 mask = ~mask;
615
616 DPRINTF("%s: block write finished\n", __func__);
617 pfl->wcycle++;
618 if (!pfl->ro) {
619
620 pflash_update(pfl, offset & mask, pfl->writeblock_size);
621 } else {
622 pfl->status |= 0x10;
623 }
624 }
625
626 pfl->counter--;
627 break;
628 default:
629 goto error_flash;
630 }
631 break;
632 case 3:
633 switch (pfl->cmd) {
634 case 0xe8:
635 if (cmd == 0xd0) {
636 pfl->wcycle = 0;
637 pfl->status |= 0x80;
638 } else {
639 DPRINTF("%s: unknown command for \"write block\"\n", __func__);
640 PFLASH_BUG("Write block confirm");
641 goto reset_flash;
642 }
643 break;
644 default:
645 goto error_flash;
646 }
647 break;
648 default:
649
650 DPRINTF("%s: invalid write state\n", __func__);
651 goto reset_flash;
652 }
653 return;
654
655 error_flash:
656 qemu_log_mask(LOG_UNIMP, "%s: Unimplemented flash cmd sequence "
657 "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)"
658 "\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
659
660 reset_flash:
661 memory_region_rom_device_set_romd(&pfl->mem, true);
662
663 pfl->wcycle = 0;
664 pfl->cmd = 0;
665}
666
667
668static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
669 unsigned len, MemTxAttrs attrs)
670{
671 pflash_t *pfl = opaque;
672 bool be = !!(pfl->features & (1 << PFLASH_BE));
673
674 if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
675 *value = pflash_data_read(opaque, addr, len, be);
676 } else {
677 *value = pflash_read(opaque, addr, len, be);
678 }
679 return MEMTX_OK;
680}
681
682static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
683 unsigned len, MemTxAttrs attrs)
684{
685 pflash_t *pfl = opaque;
686 bool be = !!(pfl->features & (1 << PFLASH_BE));
687
688 if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
689 return MEMTX_ERROR;
690 } else {
691 pflash_write(opaque, addr, value, len, be);
692 return MEMTX_OK;
693 }
694}
695
696static const MemoryRegionOps pflash_cfi01_ops = {
697 .read_with_attrs = pflash_mem_read_with_attrs,
698 .write_with_attrs = pflash_mem_write_with_attrs,
699 .endianness = DEVICE_NATIVE_ENDIAN,
700};
701
702static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
703{
704 pflash_t *pfl = CFI_PFLASH01(dev);
705 uint64_t total_len;
706 int ret;
707 uint64_t blocks_per_device, sector_len_per_device, device_len;
708 int num_devices;
709 Error *local_err = NULL;
710
711 if (pfl->sector_len == 0) {
712 error_setg(errp, "attribute \"sector-length\" not specified or zero.");
713 return;
714 }
715 if (pfl->nb_blocs == 0) {
716 error_setg(errp, "attribute \"num-blocks\" not specified or zero.");
717 return;
718 }
719 if (pfl->name == NULL) {
720 error_setg(errp, "attribute \"name\" not specified.");
721 return;
722 }
723
724 total_len = pfl->sector_len * pfl->nb_blocs;
725
726
727
728
729 num_devices = pfl->device_width ? (pfl->bank_width / pfl->device_width) : 1;
730 if (pfl->old_multiple_chip_handling) {
731 blocks_per_device = pfl->nb_blocs / num_devices;
732 sector_len_per_device = pfl->sector_len;
733 } else {
734 blocks_per_device = pfl->nb_blocs;
735 sector_len_per_device = pfl->sector_len / num_devices;
736 }
737 device_len = sector_len_per_device * blocks_per_device;
738
739
740#if 0
741 if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
742 total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
743 return NULL;
744#endif
745
746 memory_region_init_rom_device(
747 &pfl->mem, OBJECT(dev),
748 &pflash_cfi01_ops,
749 pfl,
750 pfl->name, total_len, &local_err);
751 if (local_err) {
752 error_propagate(errp, local_err);
753 return;
754 }
755
756 pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
757 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
758
759 if (pfl->blk) {
760 uint64_t perm;
761 pfl->ro = blk_is_read_only(pfl->blk);
762 perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
763 ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
764 if (ret < 0) {
765 return;
766 }
767 } else {
768 pfl->ro = 0;
769 }
770
771 if (pfl->blk) {
772
773 ret = blk_pread(pfl->blk, 0, pfl->storage, total_len);
774
775 if (ret < 0) {
776 vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
777 error_setg(errp, "failed to read the initial flash content");
778 return;
779 }
780 }
781
782
783
784
785 if (!pfl->max_device_width) {
786 pfl->max_device_width = pfl->device_width;
787 }
788
789 pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
790 pfl->wcycle = 0;
791 pfl->cmd = 0;
792 pfl->status = 0;
793
794 pfl->cfi_len = 0x52;
795
796 pfl->cfi_table[0x10] = 'Q';
797 pfl->cfi_table[0x11] = 'R';
798 pfl->cfi_table[0x12] = 'Y';
799
800 pfl->cfi_table[0x13] = 0x01;
801 pfl->cfi_table[0x14] = 0x00;
802
803 pfl->cfi_table[0x15] = 0x31;
804 pfl->cfi_table[0x16] = 0x00;
805
806 pfl->cfi_table[0x17] = 0x00;
807 pfl->cfi_table[0x18] = 0x00;
808
809 pfl->cfi_table[0x19] = 0x00;
810 pfl->cfi_table[0x1A] = 0x00;
811
812 pfl->cfi_table[0x1B] = 0x45;
813
814 pfl->cfi_table[0x1C] = 0x55;
815
816 pfl->cfi_table[0x1D] = 0x00;
817
818 pfl->cfi_table[0x1E] = 0x00;
819
820 pfl->cfi_table[0x1F] = 0x07;
821
822 pfl->cfi_table[0x20] = 0x07;
823
824 pfl->cfi_table[0x21] = 0x0a;
825
826 pfl->cfi_table[0x22] = 0x00;
827
828 pfl->cfi_table[0x23] = 0x04;
829
830 pfl->cfi_table[0x24] = 0x04;
831
832 pfl->cfi_table[0x25] = 0x04;
833
834 pfl->cfi_table[0x26] = 0x00;
835
836 pfl->cfi_table[0x27] = ctz32(device_len);
837
838 pfl->cfi_table[0x28] = 0x02;
839 pfl->cfi_table[0x29] = 0x00;
840
841 if (pfl->bank_width == 1) {
842 pfl->cfi_table[0x2A] = 0x08;
843 } else {
844 pfl->cfi_table[0x2A] = 0x0B;
845 }
846 pfl->writeblock_size = 1 << pfl->cfi_table[0x2A];
847 if (!pfl->old_multiple_chip_handling && num_devices > 1) {
848 pfl->writeblock_size *= num_devices;
849 }
850
851 pfl->cfi_table[0x2B] = 0x00;
852
853 pfl->cfi_table[0x2C] = 0x01;
854
855 pfl->cfi_table[0x2D] = blocks_per_device - 1;
856 pfl->cfi_table[0x2E] = (blocks_per_device - 1) >> 8;
857 pfl->cfi_table[0x2F] = sector_len_per_device >> 8;
858 pfl->cfi_table[0x30] = sector_len_per_device >> 16;
859
860
861 pfl->cfi_table[0x31] = 'P';
862 pfl->cfi_table[0x32] = 'R';
863 pfl->cfi_table[0x33] = 'I';
864
865 pfl->cfi_table[0x34] = '1';
866 pfl->cfi_table[0x35] = '0';
867
868 pfl->cfi_table[0x36] = 0x00;
869 pfl->cfi_table[0x37] = 0x00;
870 pfl->cfi_table[0x38] = 0x00;
871 pfl->cfi_table[0x39] = 0x00;
872
873 pfl->cfi_table[0x3a] = 0x00;
874
875 pfl->cfi_table[0x3b] = 0x00;
876 pfl->cfi_table[0x3c] = 0x00;
877
878 pfl->cfi_table[0x3f] = 0x01;
879}
880
881static Property pflash_cfi01_properties[] = {
882 DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
883
884
885
886
887
888 DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
889 DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906 DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
907 DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
908 DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
909 DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
910 DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
911 DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
912 DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
913 DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
914 DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
915 DEFINE_PROP_STRING("name", struct pflash_t, name),
916 DEFINE_PROP_BOOL("old-multiple-chip-handling", struct pflash_t,
917 old_multiple_chip_handling, false),
918 DEFINE_PROP_END_OF_LIST(),
919};
920
921static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
922{
923 DeviceClass *dc = DEVICE_CLASS(klass);
924
925 dc->realize = pflash_cfi01_realize;
926 dc->props = pflash_cfi01_properties;
927 dc->vmsd = &vmstate_pflash;
928 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
929}
930
931
932static const TypeInfo pflash_cfi01_info = {
933 .name = TYPE_CFI_PFLASH01,
934 .parent = TYPE_SYS_BUS_DEVICE,
935 .instance_size = sizeof(struct pflash_t),
936 .class_init = pflash_cfi01_class_init,
937};
938
939static void pflash_cfi01_register_types(void)
940{
941 type_register_static(&pflash_cfi01_info);
942}
943
944type_init(pflash_cfi01_register_types)
945
946pflash_t *pflash_cfi01_register(hwaddr base,
947 DeviceState *qdev, const char *name,
948 hwaddr size,
949 BlockBackend *blk,
950 uint32_t sector_len, int nb_blocs,
951 int bank_width, uint16_t id0, uint16_t id1,
952 uint16_t id2, uint16_t id3, int be)
953{
954 DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
955
956 if (blk) {
957 qdev_prop_set_drive(dev, "drive", blk, &error_abort);
958 }
959 qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
960 qdev_prop_set_uint64(dev, "sector-length", sector_len);
961 qdev_prop_set_uint8(dev, "width", bank_width);
962 qdev_prop_set_bit(dev, "big-endian", !!be);
963 qdev_prop_set_uint16(dev, "id0", id0);
964 qdev_prop_set_uint16(dev, "id1", id1);
965 qdev_prop_set_uint16(dev, "id2", id2);
966 qdev_prop_set_uint16(dev, "id3", id3);
967 qdev_prop_set_string(dev, "name", name);
968 qdev_init_nofail(dev);
969
970 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
971 return CFI_PFLASH01(dev);
972}
973
974MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
975{
976 return &fl->mem;
977}
978
979static void postload_update_cb(void *opaque, int running, RunState state)
980{
981 pflash_t *pfl = opaque;
982
983
984 qemu_del_vm_change_state_handler(pfl->vmstate);
985 pfl->vmstate = NULL;
986
987 DPRINTF("%s: updating bdrv for %s\n", __func__, pfl->name);
988 pflash_update(pfl, 0, pfl->sector_len * pfl->nb_blocs);
989}
990
991static int pflash_post_load(void *opaque, int version_id)
992{
993 pflash_t *pfl = opaque;
994
995 if (!pfl->ro) {
996 pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
997 pfl);
998 }
999 return 0;
1000}
1001