xref: /openbmc/qemu/hw/block/pflash_cfi01.c (revision 1d300b5f)
1 /*
2  *  CFI parallel flash with Intel command set emulation
3  *
4  *  Copyright (c) 2006 Thorsten Zitterell
5  *  Copyright (c) 2005 Jocelyn Mayer
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /*
22  * For now, this code can emulate flashes of 1, 2 or 4 bytes width.
23  * Supported commands/modes are:
24  * - flash read
25  * - flash write
26  * - flash ID read
27  * - sector erase
28  * - CFI queries
29  *
30  * It does not support timings
31  * It does not support flash interleaving
32  * It does not implement software data protection as found in many real chips
33  * It does not implement erase suspend/resume commands
34  * It does not implement multiple sectors erase
35  *
36  * It does not implement much more ...
37  */
38 
39 #include "hw/hw.h"
40 #include "hw/block/flash.h"
41 #include "block/block.h"
42 #include "qemu/timer.h"
43 #include "exec/address-spaces.h"
44 #include "qemu/host-utils.h"
45 #include "hw/sysbus.h"
46 
47 #define PFLASH_BUG(fmt, ...) \
48 do { \
49     fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
50     exit(1); \
51 } while(0)
52 
53 /* #define PFLASH_DEBUG */
54 #ifdef PFLASH_DEBUG
55 #define DPRINTF(fmt, ...)                                   \
56 do {                                                        \
57     fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__);       \
58 } while (0)
59 #else
60 #define DPRINTF(fmt, ...) do { } while (0)
61 #endif
62 
63 #define TYPE_CFI_PFLASH01 "cfi.pflash01"
64 #define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
65 
66 struct pflash_t {
67     /*< private >*/
68     SysBusDevice parent_obj;
69     /*< public >*/
70 
71     BlockDriverState *bs;
72     uint32_t nb_blocs;
73     uint64_t sector_len;
74     uint8_t width;
75     uint8_t be;
76     uint8_t wcycle; /* if 0, the flash is read normally */
77     int ro;
78     uint8_t cmd;
79     uint8_t status;
80     uint16_t ident0;
81     uint16_t ident1;
82     uint16_t ident2;
83     uint16_t ident3;
84     uint8_t cfi_len;
85     uint8_t cfi_table[0x52];
86     uint64_t counter;
87     unsigned int writeblock_size;
88     QEMUTimer *timer;
89     MemoryRegion mem;
90     char *name;
91     void *storage;
92 };
93 
94 static const VMStateDescription vmstate_pflash = {
95     .name = "pflash_cfi01",
96     .version_id = 1,
97     .minimum_version_id = 1,
98     .fields = (VMStateField[]) {
99         VMSTATE_UINT8(wcycle, pflash_t),
100         VMSTATE_UINT8(cmd, pflash_t),
101         VMSTATE_UINT8(status, pflash_t),
102         VMSTATE_UINT64(counter, pflash_t),
103         VMSTATE_END_OF_LIST()
104     }
105 };
106 
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     memory_region_rom_device_set_romd(&pfl->mem, true);
115     pfl->wcycle = 0;
116     pfl->cmd = 0;
117 }
118 
119 static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
120                              int width, int be)
121 {
122     hwaddr boff;
123     uint32_t ret;
124     uint8_t *p;
125 
126     ret = -1;
127     boff = offset & 0xFF; /* why this here ?? */
128 
129     if (pfl->width == 2)
130         boff = boff >> 1;
131     else if (pfl->width == 4)
132         boff = boff >> 2;
133 
134 #if 0
135     DPRINTF("%s: reading offset " TARGET_FMT_plx " under cmd %02x width %d\n",
136             __func__, offset, pfl->cmd, width);
137 #endif
138     switch (pfl->cmd) {
139     default:
140         /* This should never happen : reset state & treat it as a read */
141         DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
142         pfl->wcycle = 0;
143         pfl->cmd = 0;
144         /* fall through to read code */
145     case 0x00:
146         /* Flash area read */
147         p = pfl->storage;
148         switch (width) {
149         case 1:
150             ret = p[offset];
151             DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
152                     __func__, offset, ret);
153             break;
154         case 2:
155             if (be) {
156                 ret = p[offset] << 8;
157                 ret |= p[offset + 1];
158             } else {
159                 ret = p[offset];
160                 ret |= p[offset + 1] << 8;
161             }
162             DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
163                     __func__, offset, ret);
164             break;
165         case 4:
166             if (be) {
167                 ret = p[offset] << 24;
168                 ret |= p[offset + 1] << 16;
169                 ret |= p[offset + 2] << 8;
170                 ret |= p[offset + 3];
171             } else {
172                 ret = p[offset];
173                 ret |= p[offset + 1] << 8;
174                 ret |= p[offset + 2] << 16;
175                 ret |= p[offset + 3] << 24;
176             }
177             DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
178                     __func__, offset, ret);
179             break;
180         default:
181             DPRINTF("BUG in %s\n", __func__);
182         }
183 
184         break;
185     case 0x10: /* Single byte program */
186     case 0x20: /* Block erase */
187     case 0x28: /* Block erase */
188     case 0x40: /* single byte program */
189     case 0x50: /* Clear status register */
190     case 0x60: /* Block /un)lock */
191     case 0x70: /* Status Register */
192     case 0xe8: /* Write block */
193         /* Status register read */
194         ret = pfl->status;
195         if (width > 2) {
196             ret |= pfl->status << 16;
197         }
198         DPRINTF("%s: status %x\n", __func__, ret);
199         break;
200     case 0x90:
201         switch (boff) {
202         case 0:
203             ret = pfl->ident0 << 8 | pfl->ident1;
204             DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
205             break;
206         case 1:
207             ret = pfl->ident2 << 8 | pfl->ident3;
208             DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
209             break;
210         default:
211             DPRINTF("%s: Read Device Information boff=%x\n", __func__,
212                     (unsigned)boff);
213             ret = 0;
214             break;
215         }
216         break;
217     case 0x98: /* Query mode */
218         if (boff > pfl->cfi_len)
219             ret = 0;
220         else
221             ret = pfl->cfi_table[boff];
222         break;
223     }
224     return ret;
225 }
226 
227 /* update flash content on disk */
228 static void pflash_update(pflash_t *pfl, int offset,
229                           int size)
230 {
231     int offset_end;
232     if (pfl->bs) {
233         offset_end = offset + size;
234         /* round to sectors */
235         offset = offset >> 9;
236         offset_end = (offset_end + 511) >> 9;
237         bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
238                    offset_end - offset);
239     }
240 }
241 
242 static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
243                                      uint32_t value, int width, int be)
244 {
245     uint8_t *p = pfl->storage;
246 
247     DPRINTF("%s: block write offset " TARGET_FMT_plx
248             " value %x counter %016" PRIx64 "\n",
249             __func__, offset, value, pfl->counter);
250     switch (width) {
251     case 1:
252         p[offset] = value;
253         break;
254     case 2:
255         if (be) {
256             p[offset] = value >> 8;
257             p[offset + 1] = value;
258         } else {
259             p[offset] = value;
260             p[offset + 1] = value >> 8;
261         }
262         break;
263     case 4:
264         if (be) {
265             p[offset] = value >> 24;
266             p[offset + 1] = value >> 16;
267             p[offset + 2] = value >> 8;
268             p[offset + 3] = value;
269         } else {
270             p[offset] = value;
271             p[offset + 1] = value >> 8;
272             p[offset + 2] = value >> 16;
273             p[offset + 3] = value >> 24;
274         }
275         break;
276     }
277 
278 }
279 
280 static void pflash_write(pflash_t *pfl, hwaddr offset,
281                          uint32_t value, int width, int be)
282 {
283     uint8_t *p;
284     uint8_t cmd;
285 
286     cmd = value;
287 
288     DPRINTF("%s: writing offset " TARGET_FMT_plx " value %08x width %d wcycle 0x%x\n",
289             __func__, offset, value, width, pfl->wcycle);
290 
291     if (!pfl->wcycle) {
292         /* Set the device in I/O access mode */
293         memory_region_rom_device_set_romd(&pfl->mem, false);
294     }
295 
296     switch (pfl->wcycle) {
297     case 0:
298         /* read mode */
299         switch (cmd) {
300         case 0x00: /* ??? */
301             goto reset_flash;
302         case 0x10: /* Single Byte Program */
303         case 0x40: /* Single Byte Program */
304             DPRINTF("%s: Single Byte Program\n", __func__);
305             break;
306         case 0x20: /* Block erase */
307             p = pfl->storage;
308             offset &= ~(pfl->sector_len - 1);
309 
310             DPRINTF("%s: block erase at " TARGET_FMT_plx " bytes %x\n",
311                     __func__, offset, (unsigned)pfl->sector_len);
312 
313             if (!pfl->ro) {
314                 memset(p + offset, 0xff, pfl->sector_len);
315                 pflash_update(pfl, offset, pfl->sector_len);
316             } else {
317                 pfl->status |= 0x20; /* Block erase error */
318             }
319             pfl->status |= 0x80; /* Ready! */
320             break;
321         case 0x50: /* Clear status bits */
322             DPRINTF("%s: Clear status bits\n", __func__);
323             pfl->status = 0x0;
324             goto reset_flash;
325         case 0x60: /* Block (un)lock */
326             DPRINTF("%s: Block unlock\n", __func__);
327             break;
328         case 0x70: /* Status Register */
329             DPRINTF("%s: Read status register\n", __func__);
330             pfl->cmd = cmd;
331             return;
332         case 0x90: /* Read Device ID */
333             DPRINTF("%s: Read Device information\n", __func__);
334             pfl->cmd = cmd;
335             return;
336         case 0x98: /* CFI query */
337             DPRINTF("%s: CFI query\n", __func__);
338             break;
339         case 0xe8: /* Write to buffer */
340             DPRINTF("%s: Write to buffer\n", __func__);
341             pfl->status |= 0x80; /* Ready! */
342             break;
343         case 0xf0: /* Probe for AMD flash */
344             DPRINTF("%s: Probe for AMD flash\n", __func__);
345             goto reset_flash;
346         case 0xff: /* Read array mode */
347             DPRINTF("%s: Read array mode\n", __func__);
348             goto reset_flash;
349         default:
350             goto error_flash;
351         }
352         pfl->wcycle++;
353         pfl->cmd = cmd;
354         break;
355     case 1:
356         switch (pfl->cmd) {
357         case 0x10: /* Single Byte Program */
358         case 0x40: /* Single Byte Program */
359             DPRINTF("%s: Single Byte Program\n", __func__);
360             if (!pfl->ro) {
361                 pflash_data_write(pfl, offset, value, width, be);
362                 pflash_update(pfl, offset, width);
363             } else {
364                 pfl->status |= 0x10; /* Programming error */
365             }
366             pfl->status |= 0x80; /* Ready! */
367             pfl->wcycle = 0;
368         break;
369         case 0x20: /* Block erase */
370         case 0x28:
371             if (cmd == 0xd0) { /* confirm */
372                 pfl->wcycle = 0;
373                 pfl->status |= 0x80;
374             } else if (cmd == 0xff) { /* read array mode */
375                 goto reset_flash;
376             } else
377                 goto error_flash;
378 
379             break;
380         case 0xe8:
381             DPRINTF("%s: block write of %x bytes\n", __func__, value);
382             pfl->counter = value;
383             pfl->wcycle++;
384             break;
385         case 0x60:
386             if (cmd == 0xd0) {
387                 pfl->wcycle = 0;
388                 pfl->status |= 0x80;
389             } else if (cmd == 0x01) {
390                 pfl->wcycle = 0;
391                 pfl->status |= 0x80;
392             } else if (cmd == 0xff) {
393                 goto reset_flash;
394             } else {
395                 DPRINTF("%s: Unknown (un)locking command\n", __func__);
396                 goto reset_flash;
397             }
398             break;
399         case 0x98:
400             if (cmd == 0xff) {
401                 goto reset_flash;
402             } else {
403                 DPRINTF("%s: leaving query mode\n", __func__);
404             }
405             break;
406         default:
407             goto error_flash;
408         }
409         break;
410     case 2:
411         switch (pfl->cmd) {
412         case 0xe8: /* Block write */
413             if (!pfl->ro) {
414                 pflash_data_write(pfl, offset, value, width, be);
415             } else {
416                 pfl->status |= 0x10; /* Programming error */
417             }
418 
419             pfl->status |= 0x80;
420 
421             if (!pfl->counter) {
422                 hwaddr mask = pfl->writeblock_size - 1;
423                 mask = ~mask;
424 
425                 DPRINTF("%s: block write finished\n", __func__);
426                 pfl->wcycle++;
427                 if (!pfl->ro) {
428                     /* Flush the entire write buffer onto backing storage.  */
429                     pflash_update(pfl, offset & mask, pfl->writeblock_size);
430                 } else {
431                     pfl->status |= 0x10; /* Programming error */
432                 }
433             }
434 
435             pfl->counter--;
436             break;
437         default:
438             goto error_flash;
439         }
440         break;
441     case 3: /* Confirm mode */
442         switch (pfl->cmd) {
443         case 0xe8: /* Block write */
444             if (cmd == 0xd0) {
445                 pfl->wcycle = 0;
446                 pfl->status |= 0x80;
447             } else {
448                 DPRINTF("%s: unknown command for \"write block\"\n", __func__);
449                 PFLASH_BUG("Write block confirm");
450                 goto reset_flash;
451             }
452             break;
453         default:
454             goto error_flash;
455         }
456         break;
457     default:
458         /* Should never happen */
459         DPRINTF("%s: invalid write state\n",  __func__);
460         goto reset_flash;
461     }
462     return;
463 
464  error_flash:
465     qemu_log_mask(LOG_UNIMP, "%s: Unimplemented flash cmd sequence "
466                   "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)"
467                   "\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
468 
469  reset_flash:
470     memory_region_rom_device_set_romd(&pfl->mem, true);
471 
472     pfl->wcycle = 0;
473     pfl->cmd = 0;
474 }
475 
476 
477 static uint32_t pflash_readb_be(void *opaque, hwaddr addr)
478 {
479     return pflash_read(opaque, addr, 1, 1);
480 }
481 
482 static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
483 {
484     return pflash_read(opaque, addr, 1, 0);
485 }
486 
487 static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
488 {
489     pflash_t *pfl = opaque;
490 
491     return pflash_read(pfl, addr, 2, 1);
492 }
493 
494 static uint32_t pflash_readw_le(void *opaque, hwaddr addr)
495 {
496     pflash_t *pfl = opaque;
497 
498     return pflash_read(pfl, addr, 2, 0);
499 }
500 
501 static uint32_t pflash_readl_be(void *opaque, hwaddr addr)
502 {
503     pflash_t *pfl = opaque;
504 
505     return pflash_read(pfl, addr, 4, 1);
506 }
507 
508 static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
509 {
510     pflash_t *pfl = opaque;
511 
512     return pflash_read(pfl, addr, 4, 0);
513 }
514 
515 static void pflash_writeb_be(void *opaque, hwaddr addr,
516                              uint32_t value)
517 {
518     pflash_write(opaque, addr, value, 1, 1);
519 }
520 
521 static void pflash_writeb_le(void *opaque, hwaddr addr,
522                              uint32_t value)
523 {
524     pflash_write(opaque, addr, value, 1, 0);
525 }
526 
527 static void pflash_writew_be(void *opaque, hwaddr addr,
528                              uint32_t value)
529 {
530     pflash_t *pfl = opaque;
531 
532     pflash_write(pfl, addr, value, 2, 1);
533 }
534 
535 static void pflash_writew_le(void *opaque, hwaddr addr,
536                              uint32_t value)
537 {
538     pflash_t *pfl = opaque;
539 
540     pflash_write(pfl, addr, value, 2, 0);
541 }
542 
543 static void pflash_writel_be(void *opaque, hwaddr addr,
544                              uint32_t value)
545 {
546     pflash_t *pfl = opaque;
547 
548     pflash_write(pfl, addr, value, 4, 1);
549 }
550 
551 static void pflash_writel_le(void *opaque, hwaddr addr,
552                              uint32_t value)
553 {
554     pflash_t *pfl = opaque;
555 
556     pflash_write(pfl, addr, value, 4, 0);
557 }
558 
559 static const MemoryRegionOps pflash_cfi01_ops_be = {
560     .old_mmio = {
561         .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
562         .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
563     },
564     .endianness = DEVICE_NATIVE_ENDIAN,
565 };
566 
567 static const MemoryRegionOps pflash_cfi01_ops_le = {
568     .old_mmio = {
569         .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
570         .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
571     },
572     .endianness = DEVICE_NATIVE_ENDIAN,
573 };
574 
575 static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
576 {
577     pflash_t *pfl = CFI_PFLASH01(dev);
578     uint64_t total_len;
579     int ret;
580 
581     total_len = pfl->sector_len * pfl->nb_blocs;
582 
583     /* XXX: to be fixed */
584 #if 0
585     if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
586         total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
587         return NULL;
588 #endif
589 
590     memory_region_init_rom_device(
591         &pfl->mem, OBJECT(dev),
592         pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
593         pfl->name, total_len);
594     vmstate_register_ram(&pfl->mem, DEVICE(pfl));
595     pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
596     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
597 
598     if (pfl->bs) {
599         /* read the initial flash content */
600         ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
601 
602         if (ret < 0) {
603             vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
604             memory_region_destroy(&pfl->mem);
605             error_setg(errp, "failed to read the initial flash content");
606             return;
607         }
608     }
609 
610     if (pfl->bs) {
611         pfl->ro = bdrv_is_read_only(pfl->bs);
612     } else {
613         pfl->ro = 0;
614     }
615 
616     pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
617     pfl->wcycle = 0;
618     pfl->cmd = 0;
619     pfl->status = 0;
620     /* Hardcoded CFI table */
621     pfl->cfi_len = 0x52;
622     /* Standard "QRY" string */
623     pfl->cfi_table[0x10] = 'Q';
624     pfl->cfi_table[0x11] = 'R';
625     pfl->cfi_table[0x12] = 'Y';
626     /* Command set (Intel) */
627     pfl->cfi_table[0x13] = 0x01;
628     pfl->cfi_table[0x14] = 0x00;
629     /* Primary extended table address (none) */
630     pfl->cfi_table[0x15] = 0x31;
631     pfl->cfi_table[0x16] = 0x00;
632     /* Alternate command set (none) */
633     pfl->cfi_table[0x17] = 0x00;
634     pfl->cfi_table[0x18] = 0x00;
635     /* Alternate extended table (none) */
636     pfl->cfi_table[0x19] = 0x00;
637     pfl->cfi_table[0x1A] = 0x00;
638     /* Vcc min */
639     pfl->cfi_table[0x1B] = 0x45;
640     /* Vcc max */
641     pfl->cfi_table[0x1C] = 0x55;
642     /* Vpp min (no Vpp pin) */
643     pfl->cfi_table[0x1D] = 0x00;
644     /* Vpp max (no Vpp pin) */
645     pfl->cfi_table[0x1E] = 0x00;
646     /* Reserved */
647     pfl->cfi_table[0x1F] = 0x07;
648     /* Timeout for min size buffer write */
649     pfl->cfi_table[0x20] = 0x07;
650     /* Typical timeout for block erase */
651     pfl->cfi_table[0x21] = 0x0a;
652     /* Typical timeout for full chip erase (4096 ms) */
653     pfl->cfi_table[0x22] = 0x00;
654     /* Reserved */
655     pfl->cfi_table[0x23] = 0x04;
656     /* Max timeout for buffer write */
657     pfl->cfi_table[0x24] = 0x04;
658     /* Max timeout for block erase */
659     pfl->cfi_table[0x25] = 0x04;
660     /* Max timeout for chip erase */
661     pfl->cfi_table[0x26] = 0x00;
662     /* Device size */
663     pfl->cfi_table[0x27] = ctz32(total_len); // + 1;
664     /* Flash device interface (8 & 16 bits) */
665     pfl->cfi_table[0x28] = 0x02;
666     pfl->cfi_table[0x29] = 0x00;
667     /* Max number of bytes in multi-bytes write */
668     if (pfl->width == 1) {
669         pfl->cfi_table[0x2A] = 0x08;
670     } else {
671         pfl->cfi_table[0x2A] = 0x0B;
672     }
673     pfl->writeblock_size = 1 << pfl->cfi_table[0x2A];
674 
675     pfl->cfi_table[0x2B] = 0x00;
676     /* Number of erase block regions (uniform) */
677     pfl->cfi_table[0x2C] = 0x01;
678     /* Erase block region 1 */
679     pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
680     pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
681     pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
682     pfl->cfi_table[0x30] = pfl->sector_len >> 16;
683 
684     /* Extended */
685     pfl->cfi_table[0x31] = 'P';
686     pfl->cfi_table[0x32] = 'R';
687     pfl->cfi_table[0x33] = 'I';
688 
689     pfl->cfi_table[0x34] = '1';
690     pfl->cfi_table[0x35] = '0';
691 
692     pfl->cfi_table[0x36] = 0x00;
693     pfl->cfi_table[0x37] = 0x00;
694     pfl->cfi_table[0x38] = 0x00;
695     pfl->cfi_table[0x39] = 0x00;
696 
697     pfl->cfi_table[0x3a] = 0x00;
698 
699     pfl->cfi_table[0x3b] = 0x00;
700     pfl->cfi_table[0x3c] = 0x00;
701 
702     pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */
703 }
704 
705 static Property pflash_cfi01_properties[] = {
706     DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
707     DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
708     DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
709     DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
710     DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
711     DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
712     DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
713     DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
714     DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
715     DEFINE_PROP_STRING("name", struct pflash_t, name),
716     DEFINE_PROP_END_OF_LIST(),
717 };
718 
719 static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
720 {
721     DeviceClass *dc = DEVICE_CLASS(klass);
722 
723     dc->realize = pflash_cfi01_realize;
724     dc->props = pflash_cfi01_properties;
725     dc->vmsd = &vmstate_pflash;
726     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
727 }
728 
729 
730 static const TypeInfo pflash_cfi01_info = {
731     .name           = TYPE_CFI_PFLASH01,
732     .parent         = TYPE_SYS_BUS_DEVICE,
733     .instance_size  = sizeof(struct pflash_t),
734     .class_init     = pflash_cfi01_class_init,
735 };
736 
737 static void pflash_cfi01_register_types(void)
738 {
739     type_register_static(&pflash_cfi01_info);
740 }
741 
742 type_init(pflash_cfi01_register_types)
743 
744 pflash_t *pflash_cfi01_register(hwaddr base,
745                                 DeviceState *qdev, const char *name,
746                                 hwaddr size,
747                                 BlockDriverState *bs,
748                                 uint32_t sector_len, int nb_blocs, int width,
749                                 uint16_t id0, uint16_t id1,
750                                 uint16_t id2, uint16_t id3, int be)
751 {
752     DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
753 
754     if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
755         abort();
756     }
757     qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
758     qdev_prop_set_uint64(dev, "sector-length", sector_len);
759     qdev_prop_set_uint8(dev, "width", width);
760     qdev_prop_set_uint8(dev, "big-endian", !!be);
761     qdev_prop_set_uint16(dev, "id0", id0);
762     qdev_prop_set_uint16(dev, "id1", id1);
763     qdev_prop_set_uint16(dev, "id2", id2);
764     qdev_prop_set_uint16(dev, "id3", id3);
765     qdev_prop_set_string(dev, "name", name);
766     qdev_init_nofail(dev);
767 
768     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
769     return CFI_PFLASH01(dev);
770 }
771 
772 MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
773 {
774     return &fl->mem;
775 }
776