]>
Commit | Line | Data |
---|---|---|
c2f58c2f PD |
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" | |
778e14cc PD |
9 | #include "qemu/units.h" |
10 | #include "qapi/error.h" | |
11 | #include "sysemu/sysemu.h" | |
9cd8c41d | 12 | #include "sysemu/block-backend.h" |
c2f58c2f | 13 | #include "hw/boards.h" |
d5829a29 | 14 | #include "hw/qdev-clock.h" |
778e14cc | 15 | #include "hw/arm/aspeed_soc.h" |
d5829a29 | 16 | #include "hw/arm/boot.h" |
c2f58c2f PD |
17 | |
18 | #define TYPE_FBY35 MACHINE_TYPE_NAME("fby35") | |
19 | OBJECT_DECLARE_SIMPLE_TYPE(Fby35State, FBY35); | |
20 | ||
21 | struct Fby35State { | |
22 | MachineState parent_obj; | |
778e14cc PD |
23 | |
24 | MemoryRegion bmc_memory; | |
25 | MemoryRegion bmc_dram; | |
26 | MemoryRegion bmc_boot_rom; | |
d5829a29 PD |
27 | MemoryRegion bic_memory; |
28 | Clock *bic_sysclk; | |
778e14cc PD |
29 | |
30 | AspeedSoCState bmc; | |
d5829a29 | 31 | AspeedSoCState bic; |
9cd8c41d CLG |
32 | |
33 | bool mmio_exec; | |
c2f58c2f PD |
34 | }; |
35 | ||
778e14cc | 36 | #define FBY35_BMC_RAM_SIZE (2 * GiB) |
9cd8c41d CLG |
37 | #define FBY35_BMC_FIRMWARE_ADDR 0x0 |
38 | ||
39 | static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr, | |
40 | hwaddr offset, size_t rom_size, | |
41 | Error **errp) | |
42 | { | |
43 | BlockBackend *blk = blk_by_legacy_dinfo(dinfo); | |
44 | g_autofree void *storage = NULL; | |
45 | int64_t size; | |
46 | ||
47 | /* | |
48 | * The block backend size should have already been 'validated' by | |
49 | * the creation of the m25p80 object. | |
50 | */ | |
51 | size = blk_getlength(blk); | |
52 | if (size <= 0) { | |
53 | error_setg(errp, "failed to get flash size"); | |
54 | return; | |
55 | } | |
56 | ||
57 | if (rom_size > size) { | |
58 | rom_size = size; | |
59 | } | |
60 | ||
61 | storage = g_malloc0(rom_size); | |
62 | if (blk_pread(blk, 0, rom_size, storage, 0) < 0) { | |
63 | error_setg(errp, "failed to read the initial flash content"); | |
64 | return; | |
65 | } | |
66 | ||
67 | /* TODO: find a better way to install the ROM */ | |
68 | memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size); | |
69 | } | |
778e14cc PD |
70 | |
71 | static void fby35_bmc_init(Fby35State *s) | |
72 | { | |
9cd8c41d CLG |
73 | DriveInfo *drive0 = drive_get(IF_MTD, 0, 0); |
74 | ||
398c01da CLG |
75 | object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3"); |
76 | ||
77 | memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory", | |
78 | UINT64_MAX); | |
79 | memory_region_init_ram(&s->bmc_dram, OBJECT(&s->bmc), "bmc-dram", | |
778e14cc PD |
80 | FBY35_BMC_RAM_SIZE, &error_abort); |
81 | ||
778e14cc PD |
82 | object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE, |
83 | &error_abort); | |
84 | object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory), | |
85 | &error_abort); | |
86 | object_property_set_link(OBJECT(&s->bmc), "dram", OBJECT(&s->bmc_dram), | |
87 | &error_abort); | |
88 | object_property_set_int(OBJECT(&s->bmc), "hw-strap1", 0x000000C0, | |
89 | &error_abort); | |
90 | object_property_set_int(OBJECT(&s->bmc), "hw-strap2", 0x00000003, | |
91 | &error_abort); | |
92 | aspeed_soc_uart_set_chr(&s->bmc, ASPEED_DEV_UART5, serial_hd(0)); | |
93 | qdev_realize(DEVICE(&s->bmc), NULL, &error_abort); | |
94 | ||
95 | aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0); | |
9cd8c41d CLG |
96 | |
97 | /* Install first FMC flash content as a boot rom. */ | |
98 | if (drive0) { | |
99 | AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0]; | |
100 | MemoryRegion *boot_rom = g_new(MemoryRegion, 1); | |
101 | uint64_t size = memory_region_size(&fl->mmio); | |
102 | ||
103 | if (s->mmio_exec) { | |
104 | memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom", | |
105 | &fl->mmio, 0, size); | |
106 | memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR, | |
107 | boot_rom); | |
108 | } else { | |
109 | ||
110 | memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", | |
111 | size, &error_abort); | |
112 | memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR, | |
113 | boot_rom); | |
114 | fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR, | |
115 | size, &error_abort); | |
116 | } | |
117 | } | |
778e14cc PD |
118 | } |
119 | ||
d5829a29 PD |
120 | static void fby35_bic_init(Fby35State *s) |
121 | { | |
122 | s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK"); | |
123 | clock_set_hz(s->bic_sysclk, 200000000ULL); | |
124 | ||
d5829a29 | 125 | object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1"); |
398c01da CLG |
126 | |
127 | memory_region_init(&s->bic_memory, OBJECT(&s->bic), "bic-memory", | |
128 | UINT64_MAX); | |
129 | ||
d5829a29 PD |
130 | qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk); |
131 | object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory), | |
132 | &error_abort); | |
133 | aspeed_soc_uart_set_chr(&s->bic, ASPEED_DEV_UART5, serial_hd(1)); | |
134 | qdev_realize(DEVICE(&s->bic), NULL, &error_abort); | |
135 | ||
136 | aspeed_board_init_flashes(&s->bic.fmc, "sst25vf032b", 2, 2); | |
137 | aspeed_board_init_flashes(&s->bic.spi[0], "sst25vf032b", 2, 4); | |
138 | aspeed_board_init_flashes(&s->bic.spi[1], "sst25vf032b", 2, 6); | |
139 | } | |
140 | ||
c2f58c2f PD |
141 | static void fby35_init(MachineState *machine) |
142 | { | |
778e14cc PD |
143 | Fby35State *s = FBY35(machine); |
144 | ||
145 | fby35_bmc_init(s); | |
d5829a29 | 146 | fby35_bic_init(s); |
c2f58c2f PD |
147 | } |
148 | ||
9cd8c41d CLG |
149 | |
150 | static bool fby35_get_mmio_exec(Object *obj, Error **errp) | |
151 | { | |
152 | return FBY35(obj)->mmio_exec; | |
153 | } | |
154 | ||
155 | static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp) | |
156 | { | |
157 | FBY35(obj)->mmio_exec = value; | |
158 | } | |
159 | ||
160 | static void fby35_instance_init(Object *obj) | |
161 | { | |
162 | FBY35(obj)->mmio_exec = false; | |
163 | } | |
164 | ||
c2f58c2f PD |
165 | static void fby35_class_init(ObjectClass *oc, void *data) |
166 | { | |
167 | MachineClass *mc = MACHINE_CLASS(oc); | |
168 | ||
169 | mc->desc = "Meta Platforms fby35"; | |
170 | mc->init = fby35_init; | |
778e14cc PD |
171 | mc->no_floppy = 1; |
172 | mc->no_cdrom = 1; | |
d5829a29 | 173 | mc->min_cpus = mc->max_cpus = mc->default_cpus = 3; |
9cd8c41d CLG |
174 | |
175 | object_class_property_add_bool(oc, "execute-in-place", | |
176 | fby35_get_mmio_exec, | |
177 | fby35_set_mmio_exec); | |
178 | object_class_property_set_description(oc, "execute-in-place", | |
179 | "boot directly from CE0 flash device"); | |
c2f58c2f PD |
180 | } |
181 | ||
182 | static const TypeInfo fby35_types[] = { | |
183 | { | |
184 | .name = MACHINE_TYPE_NAME("fby35"), | |
185 | .parent = TYPE_MACHINE, | |
186 | .class_init = fby35_class_init, | |
187 | .instance_size = sizeof(Fby35State), | |
9cd8c41d | 188 | .instance_init = fby35_instance_init, |
c2f58c2f PD |
189 | }, |
190 | }; | |
191 | ||
192 | DEFINE_TYPES(fby35_types); |