xref: /qemu/hw/arm/fby35.c (revision 9cd8c41d7a41b12f36e921ba03057cb9a688d396)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
3  *
4  * This code is licensed under the GPL version 2 or later. See the COPYING
5  * file in the top-level directory.
6  */
7 
8 #include "qemu/osdep.h"
9 #include "qemu/units.h"
10 #include "qapi/error.h"
11 #include "sysemu/sysemu.h"
12 #include "sysemu/block-backend.h"
13 #include "hw/boards.h"
14 #include "hw/arm/aspeed_soc.h"
15 
16 #define TYPE_FBY35 MACHINE_TYPE_NAME("fby35")
17 OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35);
18 
19 struct Fby35State {
20     MachineState parent_obj;
21 
22     MemoryRegion bmc_memory;
23     MemoryRegion bmc_dram;
24     MemoryRegion bmc_boot_rom;
25 
26     AspeedSoCState bmc;
27 
28     bool mmio_exec;
29 };
30 
31 #define FBY35_BMC_RAM_SIZE (2 * GiB)
32 #define FBY35_BMC_FIRMWARE_ADDR 0x0
33 
34 static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
35                                      hwaddr offset, size_t rom_size,
36                                      Error **errp)
37 {
38     BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
39     g_autofree void *storage = NULL;
40     int64_t size;
41 
42     /*
43      * The block backend size should have already been 'validated' by
44      * the creation of the m25p80 object.
45      */
46     size = blk_getlength(blk);
47     if (size <= 0) {
48         error_setg(errp, "failed to get flash size");
49         return;
50     }
51 
52     if (rom_size > size) {
53         rom_size = size;
54     }
55 
56     storage = g_malloc0(rom_size);
57     if (blk_pread(blk, 0, rom_size, storage, 0) < 0) {
58         error_setg(errp, "failed to read the initial flash content");
59         return;
60     }
61 
62     /* TODO: find a better way to install the ROM */
63     memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size);
64 }
65 
66 static void fby35_bmc_init(Fby35State *s)
67 {
68     DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
69 
70     memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
71     memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
72                            FBY35_BMC_RAM_SIZE, &error_abort);
73 
74     object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3");
75     object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE,
76                             &error_abort);
77     object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory),
78                              &error_abort);
79     object_property_set_link(OBJECT(&s->bmc), "dram", OBJECT(&s->bmc_dram),
80                              &error_abort);
81     object_property_set_int(OBJECT(&s->bmc), "hw-strap1", 0x000000C0,
82                             &error_abort);
83     object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x00000003,
84                             &error_abort);
85     aspeed_soc_uart_set_chr(&s->bmc, ASPEED_DEV_UART5, serial_hd(0));
86     qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
87 
88     aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
89 
90     /* Install first FMC flash content as a boot rom. */
91     if (drive0) {
92         AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
93         MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
94         uint64_t size = memory_region_size(&fl->mmio);
95 
96         if (s->mmio_exec) {
97             memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
98                                      &fl->mmio, 0, size);
99             memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
100                                         boot_rom);
101         } else {
102 
103             memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
104                                    size, &error_abort);
105             memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
106                                         boot_rom);
107             fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
108                                      size, &error_abort);
109         }
110     }
111 }
112 
113 static void fby35_init(MachineState *machine)
114 {
115     Fby35State *s = FBY35(machine);
116 
117     fby35_bmc_init(s);
118 }
119 
120 
121 static bool fby35_get_mmio_exec(Object *obj, Error **errp)
122 {
123     return FBY35(obj)->mmio_exec;
124 }
125 
126 static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp)
127 {
128     FBY35(obj)->mmio_exec = value;
129 }
130 
131 static void fby35_instance_init(Object *obj)
132 {
133     FBY35(obj)->mmio_exec = false;
134 }
135 
136 static void fby35_class_init(ObjectClass *oc, void *data)
137 {
138     MachineClass *mc = MACHINE_CLASS(oc);
139 
140     mc->desc = "Meta Platforms fby35";
141     mc->init = fby35_init;
142     mc->no_floppy = 1;
143     mc->no_cdrom = 1;
144     mc->min_cpus = mc->max_cpus = mc->default_cpus = 2;
145 
146     object_class_property_add_bool(oc, "execute-in-place",
147                                    fby35_get_mmio_exec,
148                                    fby35_set_mmio_exec);
149     object_class_property_set_description(oc, "execute-in-place",
150                            "boot directly from CE0 flash device");
151 }
152 
153 static const TypeInfo fby35_types[] = {
154     {
155         .name = MACHINE_TYPE_NAME("fby35"),
156         .parent = TYPE_MACHINE,
157         .class_init = fby35_class_init,
158         .instance_size = sizeof(Fby35State),
159         .instance_init = fby35_instance_init,
160     },
161 };
162 
163 DEFINE_TYPES(fby35_types);
164