2 * QEMU PowerNV PNOR simple model
4 * Copyright (c) 2015-2019, IBM Corporation.
6 * This code is licensed under the GPL version 2 or later. See the
7 * COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
11 #include "qapi/error.h"
12 #include "qemu/error-report.h"
14 #include "qemu/units.h"
15 #include "sysemu/block-backend.h"
16 #include "sysemu/blockdev.h"
17 #include "hw/loader.h"
18 #include "hw/ppc/pnv_pnor.h"
19 #include "hw/qdev-properties.h"
20 #include "hw/qdev-properties-system.h"
22 static uint64_t pnv_pnor_read(void *opaque
, hwaddr addr
, unsigned size
)
24 PnvPnor
*s
= PNV_PNOR(opaque
);
28 for (i
= 0; i
< size
; i
++) {
29 ret
|= (uint64_t) s
->storage
[addr
+ i
] << (8 * (size
- i
- 1));
35 static void pnv_pnor_update(PnvPnor
*s
, int offset
, int size
)
44 offset_end
= offset
+ size
;
45 offset
= QEMU_ALIGN_DOWN(offset
, BDRV_SECTOR_SIZE
);
46 offset_end
= QEMU_ALIGN_UP(offset_end
, BDRV_SECTOR_SIZE
);
48 ret
= blk_pwrite(s
->blk
, offset
, s
->storage
+ offset
,
49 offset_end
- offset
, 0);
51 error_report("Could not update PNOR offset=0x%" PRIx32
" : %s", offset
,
56 static void pnv_pnor_write(void *opaque
, hwaddr addr
, uint64_t data
,
59 PnvPnor
*s
= PNV_PNOR(opaque
);
62 for (i
= 0; i
< size
; i
++) {
63 s
->storage
[addr
+ i
] = (data
>> (8 * (size
- i
- 1))) & 0xFF;
65 pnv_pnor_update(s
, addr
, size
);
69 * TODO: Check endianness: skiboot is BIG, Aspeed AHB is LITTLE, flash
72 static const MemoryRegionOps pnv_pnor_ops
= {
73 .read
= pnv_pnor_read
,
74 .write
= pnv_pnor_write
,
75 .endianness
= DEVICE_BIG_ENDIAN
,
82 static void pnv_pnor_realize(DeviceState
*dev
, Error
**errp
)
84 PnvPnor
*s
= PNV_PNOR(dev
);
88 uint64_t perm
= BLK_PERM_CONSISTENT_READ
|
89 (blk_is_read_only(s
->blk
) ? 0 : BLK_PERM_WRITE
);
90 ret
= blk_set_perm(s
->blk
, perm
, BLK_PERM_ALL
, errp
);
95 s
->size
= blk_getlength(s
->blk
);
97 error_setg(errp
, "failed to get flash size");
101 s
->storage
= blk_blockalign(s
->blk
, s
->size
);
103 if (blk_pread(s
->blk
, 0, s
->storage
, s
->size
) != s
->size
) {
104 error_setg(errp
, "failed to read the initial flash content");
108 s
->storage
= blk_blockalign(NULL
, s
->size
);
109 memset(s
->storage
, 0xFF, s
->size
);
112 memory_region_init_io(&s
->mmio
, OBJECT(s
), &pnv_pnor_ops
, s
,
113 TYPE_PNV_PNOR
, s
->size
);
116 static Property pnv_pnor_properties
[] = {
117 DEFINE_PROP_INT64("size", PnvPnor
, size
, 128 * MiB
),
118 DEFINE_PROP_DRIVE("drive", PnvPnor
, blk
),
119 DEFINE_PROP_END_OF_LIST(),
122 static void pnv_pnor_class_init(ObjectClass
*klass
, void *data
)
124 DeviceClass
*dc
= DEVICE_CLASS(klass
);
126 dc
->realize
= pnv_pnor_realize
;
127 device_class_set_props(dc
, pnv_pnor_properties
);
130 static const TypeInfo pnv_pnor_info
= {
131 .name
= TYPE_PNV_PNOR
,
132 .parent
= TYPE_SYS_BUS_DEVICE
,
133 .instance_size
= sizeof(PnvPnor
),
134 .class_init
= pnv_pnor_class_init
,
137 static void pnv_pnor_register_types(void)
139 type_register_static(&pnv_pnor_info
);
142 type_init(pnv_pnor_register_types
)