1 /* 2 * ASPEED SoC 2700 family 3 * 4 * Copyright (C) 2025 ASPEED Technology Inc. 5 * 6 * This code is licensed under the GPL version 2 or later. See 7 * the COPYING file in the top-level directory. 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qemu/units.h" 14 #include "qemu/datadir.h" 15 #include "qapi/error.h" 16 #include "system/block-backend.h" 17 #include "system/system.h" 18 #include "hw/arm/aspeed.h" 19 #include "hw/boards.h" 20 #include "hw/qdev-clock.h" 21 #include "hw/arm/aspeed_soc.h" 22 #include "hw/loader.h" 23 #include "hw/arm/boot.h" 24 #include "hw/block/flash.h" 25 26 27 #define TYPE_AST2700A1FC MACHINE_TYPE_NAME("ast2700fc") 28 OBJECT_DECLARE_SIMPLE_TYPE(Ast2700FCState, AST2700A1FC); 29 30 static struct arm_boot_info ast2700fc_board_info = { 31 .board_id = -1, /* device-tree-only board */ 32 }; 33 34 struct Ast2700FCState { 35 MachineState parent_obj; 36 37 MemoryRegion ca35_memory; 38 MemoryRegion ca35_dram; 39 MemoryRegion ca35_boot_rom; 40 MemoryRegion tsp_memory; 41 42 Clock *tsp_sysclk; 43 44 Aspeed27x0SoCState ca35; 45 Aspeed27x0TSPSoCState tsp; 46 47 bool mmio_exec; 48 }; 49 50 #define AST2700FC_BMC_RAM_SIZE (1 * GiB) 51 #define AST2700FC_CM4_DRAM_SIZE (32 * MiB) 52 53 #define AST2700FC_HW_STRAP1 0x000000C0 54 #define AST2700FC_HW_STRAP2 0x00000003 55 #define AST2700FC_FMC_MODEL "w25q01jvq" 56 #define AST2700FC_SPI_MODEL "w25q512jv" 57 #define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" 58 59 static void ast2700fc_ca35_load_vbootrom(AspeedSoCState *soc, 60 const char *bios_name, Error **errp) 61 { 62 g_autofree char *filename = NULL; 63 int ret; 64 65 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 66 if (!filename) { 67 error_setg(errp, "Could not find vbootrom image '%s'", bios_name); 68 return; 69 } 70 71 ret = load_image_mr(filename, &soc->vbootrom); 72 if (ret < 0) { 73 error_setg(errp, "Failed to load vbootrom image '%s'", bios_name); 74 return; 75 } 76 } 77 78 static void ast2700fc_ca35_write_boot_rom(DriveInfo *dinfo, hwaddr addr, 79 size_t rom_size, Error **errp) 80 { 81 BlockBackend *blk = blk_by_legacy_dinfo(dinfo); 82 g_autofree void *storage = NULL; 83 int64_t size; 84 85 /* 86 * The block backend size should have already been 'validated' by 87 * the creation of the m25p80 object. 88 */ 89 size = blk_getlength(blk); 90 if (size <= 0) { 91 error_setg(errp, "failed to get flash size"); 92 return; 93 } 94 95 if (rom_size > size) { 96 rom_size = size; 97 } 98 99 storage = g_malloc0(rom_size); 100 if (blk_pread(blk, 0, rom_size, storage, 0) < 0) { 101 error_setg(errp, "failed to read the initial flash content"); 102 return; 103 } 104 105 rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr); 106 } 107 108 static void ast2700fc_ca35_init(MachineState *machine) 109 { 110 Ast2700FCState *s = AST2700A1FC(machine); 111 const char *bios_name = NULL; 112 AspeedSoCState *soc; 113 AspeedSoCClass *sc; 114 uint64_t rom_size; 115 DriveInfo *mtd0; 116 117 object_initialize_child(OBJECT(s), "ca35", &s->ca35, "ast2700-a1"); 118 soc = ASPEED_SOC(&s->ca35); 119 sc = ASPEED_SOC_GET_CLASS(soc); 120 121 memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory", 122 UINT64_MAX); 123 memory_region_add_subregion(get_system_memory(), 0, &s->ca35_memory); 124 125 if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram", 126 AST2700FC_BMC_RAM_SIZE, &error_abort)) { 127 return; 128 } 129 if (!object_property_set_link(OBJECT(&s->ca35), "memory", 130 OBJECT(&s->ca35_memory), 131 &error_abort)) { 132 return; 133 }; 134 if (!object_property_set_link(OBJECT(&s->ca35), "dram", 135 OBJECT(&s->ca35_dram), &error_abort)) { 136 return; 137 } 138 if (!object_property_set_int(OBJECT(&s->ca35), "ram-size", 139 AST2700FC_BMC_RAM_SIZE, &error_abort)) { 140 return; 141 } 142 143 for (int i = 0; i < sc->macs_num; i++) { 144 if (!qemu_configure_nic_device(DEVICE(&soc->ftgmac100[i]), 145 true, NULL)) { 146 break; 147 } 148 } 149 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1", 150 AST2700FC_HW_STRAP1, &error_abort)) { 151 return; 152 } 153 if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap2", 154 AST2700FC_HW_STRAP2, &error_abort)) { 155 return; 156 } 157 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART12, serial_hd(0)); 158 aspeed_soc_uart_set_chr(ASPEED_SOC(&s->ca35.ssp), ASPEED_DEV_UART4, 159 serial_hd(1)); 160 if (!qdev_realize(DEVICE(&s->ca35), NULL, &error_abort)) { 161 return; 162 } 163 164 /* 165 * AST2700 EVB has a LM75 temperature sensor on I2C bus 0 at address 0x4d. 166 */ 167 i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "tmp105", 0x4d); 168 169 aspeed_board_init_flashes(&soc->fmc, AST2700FC_FMC_MODEL, 2, 0); 170 aspeed_board_init_flashes(&soc->spi[0], AST2700FC_SPI_MODEL, 1, 2); 171 172 ast2700fc_board_info.ram_size = machine->ram_size; 173 ast2700fc_board_info.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; 174 175 /* Install first FMC flash content as a boot rom. */ 176 if (!s->mmio_exec) { 177 mtd0 = drive_get(IF_MTD, 0, 0); 178 179 if (mtd0) { 180 rom_size = memory_region_size(&soc->spi_boot); 181 memory_region_init_rom(&s->ca35_boot_rom, NULL, "aspeed.boot_rom", 182 rom_size, &error_abort); 183 memory_region_add_subregion_overlap(&soc->spi_boot_container, 0, 184 &s->ca35_boot_rom, 1); 185 ast2700fc_ca35_write_boot_rom(mtd0, 186 sc->memmap[ASPEED_DEV_SPI_BOOT], 187 rom_size, &error_abort); 188 } 189 } 190 191 /* VBOOTROM */ 192 bios_name = machine->firmware ?: VBOOTROM_FILE_NAME; 193 ast2700fc_ca35_load_vbootrom(soc, bios_name, &error_abort); 194 195 arm_load_kernel(ARM_CPU(first_cpu), machine, &ast2700fc_board_info); 196 } 197 198 static void ast2700fc_tsp_init(MachineState *machine) 199 { 200 AspeedSoCState *soc; 201 Ast2700FCState *s = AST2700A1FC(machine); 202 s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK"); 203 clock_set_hz(s->tsp_sysclk, 200000000ULL); 204 205 object_initialize_child(OBJECT(s), "tsp", &s->tsp, TYPE_ASPEED27X0TSP_SOC); 206 memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory", 207 UINT64_MAX); 208 209 qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk); 210 if (!object_property_set_link(OBJECT(&s->tsp), "memory", 211 OBJECT(&s->tsp_memory), &error_abort)) { 212 return; 213 } 214 215 soc = ASPEED_SOC(&s->tsp); 216 aspeed_soc_uart_set_chr(soc, ASPEED_DEV_UART7, serial_hd(2)); 217 if (!qdev_realize(DEVICE(&s->tsp), NULL, &error_abort)) { 218 return; 219 } 220 } 221 222 static void ast2700fc_init(MachineState *machine) 223 { 224 ast2700fc_ca35_init(machine); 225 ast2700fc_tsp_init(machine); 226 } 227 228 static void ast2700fc_class_init(ObjectClass *oc, const void *data) 229 { 230 MachineClass *mc = MACHINE_CLASS(oc); 231 232 mc->alias = "ast2700fc"; 233 mc->desc = "ast2700 full core support"; 234 mc->init = ast2700fc_init; 235 mc->no_floppy = 1; 236 mc->no_cdrom = 1; 237 mc->min_cpus = mc->max_cpus = mc->default_cpus = 6; 238 } 239 240 static const TypeInfo ast2700fc_types[] = { 241 { 242 .name = MACHINE_TYPE_NAME("ast2700fc"), 243 .parent = TYPE_MACHINE, 244 .class_init = ast2700fc_class_init, 245 .instance_size = sizeof(Ast2700FCState), 246 }, 247 }; 248 249 DEFINE_TYPES(ast2700fc_types) 250