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"
21 static uint64_t pnv_pnor_read(void *opaque
, hwaddr addr
, unsigned size
)
23 PnvPnor
*s
= PNV_PNOR(opaque
);
27 for (i
= 0; i
< size
; i
++) {
28 ret
|= (uint64_t) s
->storage
[addr
+ i
] << (8 * (size
- i
- 1));
34 static void pnv_pnor_update(PnvPnor
*s
, int offset
, int size
)
43 offset_end
= offset
+ size
;
44 offset
= QEMU_ALIGN_DOWN(offset
, BDRV_SECTOR_SIZE
);
45 offset_end
= QEMU_ALIGN_UP(offset_end
, BDRV_SECTOR_SIZE
);
47 ret
= blk_pwrite(s
->blk
, offset
, s
->storage
+ offset
,
48 offset_end
- offset
, 0);
50 error_report("Could not update PNOR offset=0x%" PRIx32
" : %s", offset
,
55 static void pnv_pnor_write(void *opaque
, hwaddr addr
, uint64_t data
,
58 PnvPnor
*s
= PNV_PNOR(opaque
);
61 for (i
= 0; i
< size
; i
++) {
62 s
->storage
[addr
+ i
] = (data
>> (8 * (size
- i
- 1))) & 0xFF;
64 pnv_pnor_update(s
, addr
, size
);
68 * TODO: Check endianness: skiboot is BIG, Aspeed AHB is LITTLE, flash
71 static const MemoryRegionOps pnv_pnor_ops
= {
72 .read
= pnv_pnor_read
,
73 .write
= pnv_pnor_write
,
74 .endianness
= DEVICE_BIG_ENDIAN
,
81 static void pnv_pnor_realize(DeviceState
*dev
, Error
**errp
)
83 PnvPnor
*s
= PNV_PNOR(dev
);
87 uint64_t perm
= BLK_PERM_CONSISTENT_READ
|
88 (blk_is_read_only(s
->blk
) ? 0 : BLK_PERM_WRITE
);
89 ret
= blk_set_perm(s
->blk
, perm
, BLK_PERM_ALL
, errp
);
94 s
->size
= blk_getlength(s
->blk
);
96 error_setg(errp
, "failed to get flash size");
100 s
->storage
= blk_blockalign(s
->blk
, s
->size
);
102 if (blk_pread(s
->blk
, 0, s
->storage
, s
->size
) != s
->size
) {
103 error_setg(errp
, "failed to read the initial flash content");
107 s
->storage
= blk_blockalign(NULL
, s
->size
);
108 memset(s
->storage
, 0xFF, s
->size
);
111 memory_region_init_io(&s
->mmio
, OBJECT(s
), &pnv_pnor_ops
, s
,
112 TYPE_PNV_PNOR
, s
->size
);
115 static Property pnv_pnor_properties
[] = {
116 DEFINE_PROP_INT64("size", PnvPnor
, size
, 128 * MiB
),
117 DEFINE_PROP_DRIVE("drive", PnvPnor
, blk
),
118 DEFINE_PROP_END_OF_LIST(),
121 static void pnv_pnor_class_init(ObjectClass
*klass
, void *data
)
123 DeviceClass
*dc
= DEVICE_CLASS(klass
);
125 dc
->realize
= pnv_pnor_realize
;
126 device_class_set_props(dc
, pnv_pnor_properties
);
129 static const TypeInfo pnv_pnor_info
= {
130 .name
= TYPE_PNV_PNOR
,
131 .parent
= TYPE_SYS_BUS_DEVICE
,
132 .instance_size
= sizeof(PnvPnor
),
133 .class_init
= pnv_pnor_class_init
,
136 static void pnv_pnor_register_types(void)
138 type_register_static(&pnv_pnor_info
);
141 type_init(pnv_pnor_register_types
)