qemu-img: Gracefully shutdown when map can't finish
[qemu/ar7.git] / hw / block / pflash_cfi02.c
blobf2c6201f813e77cc452483119afecc833ba62eaf
1 /*
2 * CFI parallel flash with AMD command set emulation
4 * Copyright (c) 2005 Jocelyn Mayer
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
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
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
38 #include "qemu/osdep.h"
39 #include "hw/hw.h"
40 #include "hw/block/block.h"
41 #include "hw/block/flash.h"
42 #include "qapi/error.h"
43 #include "qemu/timer.h"
44 #include "sysemu/block-backend.h"
45 #include "qemu/host-utils.h"
46 #include "hw/sysbus.h"
47 #include "trace.h"
49 //#define PFLASH_DEBUG
50 #ifdef PFLASH_DEBUG
51 #define DPRINTF(fmt, ...) \
52 do { \
53 fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \
54 } while (0)
55 #else
56 #define DPRINTF(fmt, ...) do { } while (0)
57 #endif
59 #define PFLASH_LAZY_ROMD_THRESHOLD 42
61 struct PFlashCFI02 {
62 /*< private >*/
63 SysBusDevice parent_obj;
64 /*< public >*/
66 BlockBackend *blk;
67 uint32_t sector_len;
68 uint32_t nb_blocs;
69 uint32_t chip_len;
70 uint8_t mappings;
71 uint8_t width;
72 uint8_t be;
73 int wcycle; /* if 0, the flash is read normally */
74 int bypass;
75 int ro;
76 uint8_t cmd;
77 uint8_t status;
78 /* FIXME: implement array device properties */
79 uint16_t ident0;
80 uint16_t ident1;
81 uint16_t ident2;
82 uint16_t ident3;
83 uint16_t unlock_addr0;
84 uint16_t unlock_addr1;
85 uint8_t cfi_table[0x52];
86 QEMUTimer timer;
87 /* The device replicates the flash memory across its memory space. Emulate
88 * that by having a container (.mem) filled with an array of aliases
89 * (.mem_mappings) pointing to the flash memory (.orig_mem).
91 MemoryRegion mem;
92 MemoryRegion *mem_mappings; /* array; one per mapping */
93 MemoryRegion orig_mem;
94 int rom_mode;
95 int read_counter; /* used for lazy switch-back to rom mode */
96 char *name;
97 void *storage;
101 * Set up replicated mappings of the same region.
103 static void pflash_setup_mappings(PFlashCFI02 *pfl)
105 unsigned i;
106 hwaddr size = memory_region_size(&pfl->orig_mem);
108 memory_region_init(&pfl->mem, OBJECT(pfl), "pflash", pfl->mappings * size);
109 pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings);
110 for (i = 0; i < pfl->mappings; ++i) {
111 memory_region_init_alias(&pfl->mem_mappings[i], OBJECT(pfl),
112 "pflash-alias", &pfl->orig_mem, 0, size);
113 memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]);
117 static void pflash_register_memory(PFlashCFI02 *pfl, int rom_mode)
119 memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
120 pfl->rom_mode = rom_mode;
123 static void pflash_timer (void *opaque)
125 PFlashCFI02 *pfl = opaque;
127 trace_pflash_timer_expired(pfl->cmd);
128 /* Reset flash */
129 pfl->status ^= 0x80;
130 if (pfl->bypass) {
131 pfl->wcycle = 2;
132 } else {
133 pflash_register_memory(pfl, 1);
134 pfl->wcycle = 0;
136 pfl->cmd = 0;
139 static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset,
140 int width, int be)
142 hwaddr boff;
143 uint32_t ret;
144 uint8_t *p;
146 ret = -1;
147 trace_pflash_read(offset, pfl->cmd, width, pfl->wcycle);
148 /* Lazy reset to ROMD mode after a certain amount of read accesses */
149 if (!pfl->rom_mode && pfl->wcycle == 0 &&
150 ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) {
151 pflash_register_memory(pfl, 1);
153 offset &= pfl->chip_len - 1;
154 boff = offset & 0xFF;
155 if (pfl->width == 2)
156 boff = boff >> 1;
157 else if (pfl->width == 4)
158 boff = boff >> 2;
159 switch (pfl->cmd) {
160 default:
161 /* This should never happen : reset state & treat it as a read*/
162 DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
163 pfl->wcycle = 0;
164 pfl->cmd = 0;
165 /* fall through to the read code */
166 case 0x80:
167 /* We accept reads during second unlock sequence... */
168 case 0x00:
169 flash_read:
170 /* Flash area read */
171 p = pfl->storage;
172 switch (width) {
173 case 1:
174 ret = p[offset];
175 trace_pflash_data_read8(offset, ret);
176 break;
177 case 2:
178 if (be) {
179 ret = p[offset] << 8;
180 ret |= p[offset + 1];
181 } else {
182 ret = p[offset];
183 ret |= p[offset + 1] << 8;
185 trace_pflash_data_read16(offset, ret);
186 break;
187 case 4:
188 if (be) {
189 ret = p[offset] << 24;
190 ret |= p[offset + 1] << 16;
191 ret |= p[offset + 2] << 8;
192 ret |= p[offset + 3];
193 } else {
194 ret = p[offset];
195 ret |= p[offset + 1] << 8;
196 ret |= p[offset + 2] << 16;
197 ret |= p[offset + 3] << 24;
199 trace_pflash_data_read32(offset, ret);
200 break;
202 break;
203 case 0x90:
204 /* flash ID read */
205 switch (boff) {
206 case 0x00:
207 case 0x01:
208 ret = boff & 0x01 ? pfl->ident1 : pfl->ident0;
209 break;
210 case 0x02:
211 ret = 0x00; /* Pretend all sectors are unprotected */
212 break;
213 case 0x0E:
214 case 0x0F:
215 ret = boff & 0x01 ? pfl->ident3 : pfl->ident2;
216 if (ret == (uint8_t)-1) {
217 goto flash_read;
219 break;
220 default:
221 goto flash_read;
223 DPRINTF("%s: ID " TARGET_FMT_plx " %x\n", __func__, boff, ret);
224 break;
225 case 0xA0:
226 case 0x10:
227 case 0x30:
228 /* Status register read */
229 ret = pfl->status;
230 DPRINTF("%s: status %x\n", __func__, ret);
231 /* Toggle bit 6 */
232 pfl->status ^= 0x40;
233 break;
234 case 0x98:
235 /* CFI query mode */
236 if (boff < sizeof(pfl->cfi_table)) {
237 ret = pfl->cfi_table[boff];
238 } else {
239 ret = 0;
241 break;
244 return ret;
247 /* update flash content on disk */
248 static void pflash_update(PFlashCFI02 *pfl, int offset,
249 int size)
251 int offset_end;
252 if (pfl->blk) {
253 offset_end = offset + size;
254 /* widen to sector boundaries */
255 offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
256 offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
257 blk_pwrite(pfl->blk, offset, pfl->storage + offset,
258 offset_end - offset, 0);
262 static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
263 uint32_t value, int width, int be)
265 hwaddr boff;
266 uint8_t *p;
267 uint8_t cmd;
269 cmd = value;
270 if (pfl->cmd != 0xA0 && cmd == 0xF0) {
271 #if 0
272 DPRINTF("%s: flash reset asked (%02x %02x)\n",
273 __func__, pfl->cmd, cmd);
274 #endif
275 goto reset_flash;
277 trace_pflash_write(offset, value, width, pfl->wcycle);
278 offset &= pfl->chip_len - 1;
280 DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d\n", __func__,
281 offset, value, width);
282 boff = offset & (pfl->sector_len - 1);
283 if (pfl->width == 2)
284 boff = boff >> 1;
285 else if (pfl->width == 4)
286 boff = boff >> 2;
287 switch (pfl->wcycle) {
288 case 0:
289 /* Set the device in I/O access mode if required */
290 if (pfl->rom_mode)
291 pflash_register_memory(pfl, 0);
292 pfl->read_counter = 0;
293 /* We're in read mode */
294 check_unlock0:
295 if (boff == 0x55 && cmd == 0x98) {
296 enter_CFI_mode:
297 /* Enter CFI query mode */
298 pfl->wcycle = 7;
299 pfl->cmd = 0x98;
300 return;
302 if (boff != pfl->unlock_addr0 || cmd != 0xAA) {
303 DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n",
304 __func__, boff, cmd, pfl->unlock_addr0);
305 goto reset_flash;
307 DPRINTF("%s: unlock sequence started\n", __func__);
308 break;
309 case 1:
310 /* We started an unlock sequence */
311 check_unlock1:
312 if (boff != pfl->unlock_addr1 || cmd != 0x55) {
313 DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__,
314 boff, cmd);
315 goto reset_flash;
317 DPRINTF("%s: unlock sequence done\n", __func__);
318 break;
319 case 2:
320 /* We finished an unlock sequence */
321 if (!pfl->bypass && boff != pfl->unlock_addr0) {
322 DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__,
323 boff, cmd);
324 goto reset_flash;
326 switch (cmd) {
327 case 0x20:
328 pfl->bypass = 1;
329 goto do_bypass;
330 case 0x80:
331 case 0x90:
332 case 0xA0:
333 pfl->cmd = cmd;
334 DPRINTF("%s: starting command %02x\n", __func__, cmd);
335 break;
336 default:
337 DPRINTF("%s: unknown command %02x\n", __func__, cmd);
338 goto reset_flash;
340 break;
341 case 3:
342 switch (pfl->cmd) {
343 case 0x80:
344 /* We need another unlock sequence */
345 goto check_unlock0;
346 case 0xA0:
347 trace_pflash_data_write(offset, value, width, 0);
348 p = pfl->storage;
349 if (!pfl->ro) {
350 switch (width) {
351 case 1:
352 p[offset] &= value;
353 pflash_update(pfl, offset, 1);
354 break;
355 case 2:
356 if (be) {
357 p[offset] &= value >> 8;
358 p[offset + 1] &= value;
359 } else {
360 p[offset] &= value;
361 p[offset + 1] &= value >> 8;
363 pflash_update(pfl, offset, 2);
364 break;
365 case 4:
366 if (be) {
367 p[offset] &= value >> 24;
368 p[offset + 1] &= value >> 16;
369 p[offset + 2] &= value >> 8;
370 p[offset + 3] &= value;
371 } else {
372 p[offset] &= value;
373 p[offset + 1] &= value >> 8;
374 p[offset + 2] &= value >> 16;
375 p[offset + 3] &= value >> 24;
377 pflash_update(pfl, offset, 4);
378 break;
381 pfl->status = 0x00 | ~(value & 0x80);
382 /* Let's pretend write is immediate */
383 if (pfl->bypass)
384 goto do_bypass;
385 goto reset_flash;
386 case 0x90:
387 if (pfl->bypass && cmd == 0x00) {
388 /* Unlock bypass reset */
389 goto reset_flash;
391 /* We can enter CFI query mode from autoselect mode */
392 if (boff == 0x55 && cmd == 0x98)
393 goto enter_CFI_mode;
394 /* No break here */
395 default:
396 DPRINTF("%s: invalid write for command %02x\n",
397 __func__, pfl->cmd);
398 goto reset_flash;
400 case 4:
401 switch (pfl->cmd) {
402 case 0xA0:
403 /* Ignore writes while flash data write is occurring */
404 /* As we suppose write is immediate, this should never happen */
405 return;
406 case 0x80:
407 goto check_unlock1;
408 default:
409 /* Should never happen */
410 DPRINTF("%s: invalid command state %02x (wc 4)\n",
411 __func__, pfl->cmd);
412 goto reset_flash;
414 break;
415 case 5:
416 switch (cmd) {
417 case 0x10:
418 if (boff != pfl->unlock_addr0) {
419 DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n",
420 __func__, offset);
421 goto reset_flash;
423 /* Chip erase */
424 DPRINTF("%s: start chip erase\n", __func__);
425 if (!pfl->ro) {
426 memset(pfl->storage, 0xFF, pfl->chip_len);
427 pflash_update(pfl, 0, pfl->chip_len);
429 pfl->status = 0x00;
430 /* Let's wait 5 seconds before chip erase is done */
431 timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
432 (NANOSECONDS_PER_SECOND * 5));
433 break;
434 case 0x30:
435 /* Sector erase */
436 p = pfl->storage;
437 offset &= ~(pfl->sector_len - 1);
438 DPRINTF("%s: start sector erase at " TARGET_FMT_plx "\n", __func__,
439 offset);
440 if (!pfl->ro) {
441 memset(p + offset, 0xFF, pfl->sector_len);
442 pflash_update(pfl, offset, pfl->sector_len);
444 pfl->status = 0x00;
445 /* Let's wait 1/2 second before sector erase is done */
446 timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
447 (NANOSECONDS_PER_SECOND / 2));
448 break;
449 default:
450 DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
451 goto reset_flash;
453 pfl->cmd = cmd;
454 break;
455 case 6:
456 switch (pfl->cmd) {
457 case 0x10:
458 /* Ignore writes during chip erase */
459 return;
460 case 0x30:
461 /* Ignore writes during sector erase */
462 return;
463 default:
464 /* Should never happen */
465 DPRINTF("%s: invalid command state %02x (wc 6)\n",
466 __func__, pfl->cmd);
467 goto reset_flash;
469 break;
470 case 7: /* Special value for CFI queries */
471 DPRINTF("%s: invalid write in CFI query mode\n", __func__);
472 goto reset_flash;
473 default:
474 /* Should never happen */
475 DPRINTF("%s: invalid write state (wc 7)\n", __func__);
476 goto reset_flash;
478 pfl->wcycle++;
480 return;
482 /* Reset flash */
483 reset_flash:
484 trace_pflash_reset();
485 pfl->bypass = 0;
486 pfl->wcycle = 0;
487 pfl->cmd = 0;
488 return;
490 do_bypass:
491 pfl->wcycle = 2;
492 pfl->cmd = 0;
495 static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size)
497 return pflash_read(opaque, addr, size, 1);
500 static void pflash_be_writefn(void *opaque, hwaddr addr,
501 uint64_t value, unsigned size)
503 pflash_write(opaque, addr, value, size, 1);
506 static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size)
508 return pflash_read(opaque, addr, size, 0);
511 static void pflash_le_writefn(void *opaque, hwaddr addr,
512 uint64_t value, unsigned size)
514 pflash_write(opaque, addr, value, size, 0);
517 static const MemoryRegionOps pflash_cfi02_ops_be = {
518 .read = pflash_be_readfn,
519 .write = pflash_be_writefn,
520 .valid.min_access_size = 1,
521 .valid.max_access_size = 4,
522 .endianness = DEVICE_NATIVE_ENDIAN,
525 static const MemoryRegionOps pflash_cfi02_ops_le = {
526 .read = pflash_le_readfn,
527 .write = pflash_le_writefn,
528 .valid.min_access_size = 1,
529 .valid.max_access_size = 4,
530 .endianness = DEVICE_NATIVE_ENDIAN,
533 static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
535 PFlashCFI02 *pfl = PFLASH_CFI02(dev);
536 uint32_t chip_len;
537 int ret;
538 Error *local_err = NULL;
540 if (pfl->sector_len == 0) {
541 error_setg(errp, "attribute \"sector-length\" not specified or zero.");
542 return;
544 if (pfl->nb_blocs == 0) {
545 error_setg(errp, "attribute \"num-blocks\" not specified or zero.");
546 return;
548 if (pfl->name == NULL) {
549 error_setg(errp, "attribute \"name\" not specified.");
550 return;
553 chip_len = pfl->sector_len * pfl->nb_blocs;
555 memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ?
556 &pflash_cfi02_ops_be : &pflash_cfi02_ops_le,
557 pfl, pfl->name, chip_len, &local_err);
558 if (local_err) {
559 error_propagate(errp, local_err);
560 return;
563 pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
564 pfl->chip_len = chip_len;
566 if (pfl->blk) {
567 uint64_t perm;
568 pfl->ro = blk_is_read_only(pfl->blk);
569 perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
570 ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
571 if (ret < 0) {
572 return;
574 } else {
575 pfl->ro = 0;
578 if (pfl->blk) {
579 if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, chip_len,
580 errp)) {
581 vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl));
582 return;
586 pflash_setup_mappings(pfl);
587 pfl->rom_mode = 1;
588 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
590 timer_init_ns(&pfl->timer, QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
591 pfl->wcycle = 0;
592 pfl->cmd = 0;
593 pfl->status = 0;
594 /* Hardcoded CFI table (mostly from SG29 Spansion flash) */
595 /* Standard "QRY" string */
596 pfl->cfi_table[0x10] = 'Q';
597 pfl->cfi_table[0x11] = 'R';
598 pfl->cfi_table[0x12] = 'Y';
599 /* Command set (AMD/Fujitsu) */
600 pfl->cfi_table[0x13] = 0x02;
601 pfl->cfi_table[0x14] = 0x00;
602 /* Primary extended table address */
603 pfl->cfi_table[0x15] = 0x31;
604 pfl->cfi_table[0x16] = 0x00;
605 /* Alternate command set (none) */
606 pfl->cfi_table[0x17] = 0x00;
607 pfl->cfi_table[0x18] = 0x00;
608 /* Alternate extended table (none) */
609 pfl->cfi_table[0x19] = 0x00;
610 pfl->cfi_table[0x1A] = 0x00;
611 /* Vcc min */
612 pfl->cfi_table[0x1B] = 0x27;
613 /* Vcc max */
614 pfl->cfi_table[0x1C] = 0x36;
615 /* Vpp min (no Vpp pin) */
616 pfl->cfi_table[0x1D] = 0x00;
617 /* Vpp max (no Vpp pin) */
618 pfl->cfi_table[0x1E] = 0x00;
619 /* Reserved */
620 pfl->cfi_table[0x1F] = 0x07;
621 /* Timeout for min size buffer write (NA) */
622 pfl->cfi_table[0x20] = 0x00;
623 /* Typical timeout for block erase (512 ms) */
624 pfl->cfi_table[0x21] = 0x09;
625 /* Typical timeout for full chip erase (4096 ms) */
626 pfl->cfi_table[0x22] = 0x0C;
627 /* Reserved */
628 pfl->cfi_table[0x23] = 0x01;
629 /* Max timeout for buffer write (NA) */
630 pfl->cfi_table[0x24] = 0x00;
631 /* Max timeout for block erase */
632 pfl->cfi_table[0x25] = 0x0A;
633 /* Max timeout for chip erase */
634 pfl->cfi_table[0x26] = 0x0D;
635 /* Device size */
636 pfl->cfi_table[0x27] = ctz32(chip_len);
637 /* Flash device interface (8 & 16 bits) */
638 pfl->cfi_table[0x28] = 0x02;
639 pfl->cfi_table[0x29] = 0x00;
640 /* Max number of bytes in multi-bytes write */
641 /* XXX: disable buffered write as it's not supported */
642 // pfl->cfi_table[0x2A] = 0x05;
643 pfl->cfi_table[0x2A] = 0x00;
644 pfl->cfi_table[0x2B] = 0x00;
645 /* Number of erase block regions (uniform) */
646 pfl->cfi_table[0x2C] = 0x01;
647 /* Erase block region 1 */
648 pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
649 pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
650 pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
651 pfl->cfi_table[0x30] = pfl->sector_len >> 16;
653 /* Extended */
654 pfl->cfi_table[0x31] = 'P';
655 pfl->cfi_table[0x32] = 'R';
656 pfl->cfi_table[0x33] = 'I';
658 pfl->cfi_table[0x34] = '1';
659 pfl->cfi_table[0x35] = '0';
661 pfl->cfi_table[0x36] = 0x00;
662 pfl->cfi_table[0x37] = 0x00;
663 pfl->cfi_table[0x38] = 0x00;
664 pfl->cfi_table[0x39] = 0x00;
666 pfl->cfi_table[0x3a] = 0x00;
668 pfl->cfi_table[0x3b] = 0x00;
669 pfl->cfi_table[0x3c] = 0x00;
672 static Property pflash_cfi02_properties[] = {
673 DEFINE_PROP_DRIVE("drive", PFlashCFI02, blk),
674 DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, nb_blocs, 0),
675 DEFINE_PROP_UINT32("sector-length", PFlashCFI02, sector_len, 0),
676 DEFINE_PROP_UINT8("width", PFlashCFI02, width, 0),
677 DEFINE_PROP_UINT8("mappings", PFlashCFI02, mappings, 0),
678 DEFINE_PROP_UINT8("big-endian", PFlashCFI02, be, 0),
679 DEFINE_PROP_UINT16("id0", PFlashCFI02, ident0, 0),
680 DEFINE_PROP_UINT16("id1", PFlashCFI02, ident1, 0),
681 DEFINE_PROP_UINT16("id2", PFlashCFI02, ident2, 0),
682 DEFINE_PROP_UINT16("id3", PFlashCFI02, ident3, 0),
683 DEFINE_PROP_UINT16("unlock-addr0", PFlashCFI02, unlock_addr0, 0),
684 DEFINE_PROP_UINT16("unlock-addr1", PFlashCFI02, unlock_addr1, 0),
685 DEFINE_PROP_STRING("name", PFlashCFI02, name),
686 DEFINE_PROP_END_OF_LIST(),
689 static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp)
691 PFlashCFI02 *pfl = PFLASH_CFI02(dev);
692 timer_del(&pfl->timer);
695 static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
697 DeviceClass *dc = DEVICE_CLASS(klass);
699 dc->realize = pflash_cfi02_realize;
700 dc->unrealize = pflash_cfi02_unrealize;
701 dc->props = pflash_cfi02_properties;
702 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
705 static const TypeInfo pflash_cfi02_info = {
706 .name = TYPE_PFLASH_CFI02,
707 .parent = TYPE_SYS_BUS_DEVICE,
708 .instance_size = sizeof(PFlashCFI02),
709 .class_init = pflash_cfi02_class_init,
712 static void pflash_cfi02_register_types(void)
714 type_register_static(&pflash_cfi02_info);
717 type_init(pflash_cfi02_register_types)
719 PFlashCFI02 *pflash_cfi02_register(hwaddr base,
720 const char *name,
721 hwaddr size,
722 BlockBackend *blk,
723 uint32_t sector_len,
724 int nb_mappings, int width,
725 uint16_t id0, uint16_t id1,
726 uint16_t id2, uint16_t id3,
727 uint16_t unlock_addr0,
728 uint16_t unlock_addr1,
729 int be)
731 DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI02);
733 if (blk) {
734 qdev_prop_set_drive(dev, "drive", blk, &error_abort);
736 assert(size % sector_len == 0);
737 qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
738 qdev_prop_set_uint32(dev, "sector-length", sector_len);
739 qdev_prop_set_uint8(dev, "width", width);
740 qdev_prop_set_uint8(dev, "mappings", nb_mappings);
741 qdev_prop_set_uint8(dev, "big-endian", !!be);
742 qdev_prop_set_uint16(dev, "id0", id0);
743 qdev_prop_set_uint16(dev, "id1", id1);
744 qdev_prop_set_uint16(dev, "id2", id2);
745 qdev_prop_set_uint16(dev, "id3", id3);
746 qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0);
747 qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1);
748 qdev_prop_set_string(dev, "name", name);
749 qdev_init_nofail(dev);
751 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
752 return PFLASH_CFI02(dev);