| 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 "qapi/error.h" |
| 15 | #include "system/block-backend.h" |
| 16 | #include "system/system.h" |
| 17 | #include "hw/arm/aspeed.h" |
| 18 | #include "hw/core/boards.h" |
| 19 | #include "hw/core/qdev-clock.h" |
| 20 | #include "hw/arm/aspeed_soc.h" |
| 21 | #include "hw/core/loader.h" |
| 22 | #include "hw/arm/boot.h" |
| 23 | #include "hw/block/flash.h" |
| 24 | #include "hw/arm/aspeed_coprocessor.h" |
| 25 | #include "hw/arm/machines-qom.h" |
| 26 | |
| 27 | #define TYPE_AST2700FC MACHINE_TYPE_NAME("ast2700fc") |
| 28 | OBJECT_DECLARE_SIMPLE_TYPE(Ast2700FCState, AST2700FC); |
| 29 | |
| 30 | struct Ast2700FCState { |
| 31 | MachineState parent_obj; |
| 32 | |
| 33 | MemoryRegion ca35_memory; |
| 34 | MemoryRegion ca35_dram; |
| 35 | MemoryRegion ca35_boot_rom; |
| 36 | MemoryRegion ssp_memory; |
| 37 | MemoryRegion tsp_memory; |
| 38 | |
| 39 | Clock *ssp_sysclk; |
| 40 | Clock *tsp_sysclk; |
| 41 | |
| 42 | Aspeed27x0SoCState ca35; |
| 43 | Aspeed27x0CoprocessorState ssp; |
| 44 | Aspeed27x0CoprocessorState tsp; |
| 45 | |
| 46 | struct arm_boot_info bootinfo; |
| 47 | }; |
| 48 | |
| 49 | #define AST2700FC_BMC_RAM_SIZE (2 * GiB) |
| 50 | |
| 51 | /* SCU HW Strap1 */ |
| 52 | #define AST2700FC_HW_STRAP1 0x00000800 |
| 53 | /* SCUIO HW Strap1 */ |
| 54 | #define AST2700FC_HW_STRAP2 0x00000700 |
| 55 | #define AST2700FC_FMC_MODEL "w25q01jvq" |
| 56 | #define AST2700FC_SPI_MODEL "w25q512jv" |
| 57 | |
| 58 | static bool ast2700fc_ca35_init(MachineState *machine, Error **errp) |
| 59 | { |
| 60 | Ast2700FCState *s = AST2700FC(machine); |
| 61 | AspeedSoCState *soc; |
| 62 | AspeedSoCClass *sc; |
| 63 | const char *bios_name = NULL; |
| 64 | BlockBackend *fmc0 = NULL; |
| 65 | DeviceState *dev = NULL; |
| 66 | uint64_t rom_size; |
| 67 | |
| 68 | object_initialize_child(OBJECT(s), "ca35", &s->ca35, "ast2700-a2"); |
| 69 | soc = ASPEED_SOC(&s->ca35); |
| 70 | sc = ASPEED_SOC_GET_CLASS(soc); |
| 71 | |
| 72 | memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory", |
| 73 | UINT64_MAX); |
| 74 | memory_region_add_subregion(get_system_memory(), 0, &s->ca35_memory); |
| 75 | |
| 76 | if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram", |
| 77 | AST2700FC_BMC_RAM_SIZE, errp)) { |
| 78 | return false; |
| 79 | } |
| 80 | object_property_set_link(OBJECT(&s->ca35), "memory", |
| 81 | OBJECT(&s->ca35_memory), &error_abort); |
| 82 | object_property_set_link(OBJECT(&s->ca35), "dram", OBJECT(&s->ca35_dram), |
| 83 | &error_abort); |
| 84 | object_property_set_int(OBJECT(&s->ca35), "ram-size", |
| 85 | AST2700FC_BMC_RAM_SIZE, &error_abort); |
| 86 | |
| 87 | for (int i = 0; i < sc->macs_num; i++) { |
| 88 | if (!qemu_configure_nic_device(DEVICE(&soc->ftgmac100[i]), |
| 89 | true, NULL)) { |
| 90 | break; |
| 91 | } |
| 92 | } |
| 93 | object_property_set_int(OBJECT(&s->ca35), "hw-strap1", |
| 94 | AST2700FC_HW_STRAP1, &error_abort); |
| 95 | object_property_set_int(OBJECT(&s->ca35), "hw-strap2", |
| 96 | AST2700FC_HW_STRAP2, &error_abort); |
| 97 | aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART12, sc->uarts_base, |
| 98 | sc->uarts_num, serial_hd(0)); |
| 99 | aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART4, sc->uarts_base, |
| 100 | sc->uarts_num, serial_hd(1)); |
| 101 | aspeed_soc_uart_set_chr(soc->uart, ASPEED_DEV_UART7, sc->uarts_base, |
| 102 | sc->uarts_num, serial_hd(2)); |
| 103 | if (!qdev_realize(DEVICE(&s->ca35), NULL, errp)) { |
| 104 | return false; |
| 105 | } |
| 106 | |
| 107 | /* |
| 108 | * AST2700 EVB has a LM75 temperature sensor on I2C bus 0 at address 0x4d. |
| 109 | */ |
| 110 | i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "tmp105", 0x4d); |
| 111 | |
| 112 | aspeed_board_init_flashes(&soc->fmc, AST2700FC_FMC_MODEL, 2, 0); |
| 113 | aspeed_board_init_flashes(&soc->spi[0], AST2700FC_SPI_MODEL, 1, 2); |
| 114 | |
| 115 | s->bootinfo.ram_size = machine->ram_size; |
| 116 | s->bootinfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; |
| 117 | s->bootinfo.board_id = -1; /* device-tree-only board */ |
| 118 | |
| 119 | dev = ssi_get_cs(soc->fmc.spi, 0); |
| 120 | fmc0 = dev ? m25p80_get_blk(dev) : NULL; |
| 121 | |
| 122 | if (fmc0) { |
| 123 | rom_size = memory_region_size(&soc->spi_boot); |
| 124 | aspeed_install_boot_rom(soc, fmc0, &s->ca35_boot_rom, rom_size); |
| 125 | } |
| 126 | |
| 127 | /* VBOOTROM */ |
| 128 | bios_name = machine->firmware ?: VBOOTROM_FILE_NAME; |
| 129 | aspeed_load_vbootrom(soc, bios_name, errp); |
| 130 | |
| 131 | arm_load_kernel(ARM_CPU(first_cpu), machine, &s->bootinfo); |
| 132 | |
| 133 | return true; |
| 134 | } |
| 135 | |
| 136 | static bool ast2700fc_ssp_init(Ast2700FCState *s, AspeedSoCState *psp, |
| 137 | Error **errp) |
| 138 | { |
| 139 | s->ssp_sysclk = clock_new(OBJECT(s), "SSP_SYSCLK"); |
| 140 | clock_set_hz(s->ssp_sysclk, 200000000ULL); |
| 141 | |
| 142 | object_initialize_child(OBJECT(s), "ssp", &s->ssp, |
| 143 | TYPE_ASPEED27X0SSP_COPROCESSOR); |
| 144 | memory_region_init(&s->ssp_memory, OBJECT(&s->ssp), "ssp-memory", |
| 145 | UINT64_MAX); |
| 146 | |
| 147 | qdev_connect_clock_in(DEVICE(&s->ssp), "sysclk", s->ssp_sysclk); |
| 148 | object_property_set_link(OBJECT(&s->ssp), "memory", |
| 149 | OBJECT(&s->ssp_memory), &error_abort); |
| 150 | |
| 151 | object_property_set_link(OBJECT(&s->ssp), "uart", |
| 152 | OBJECT(&psp->uart[4]), &error_abort); |
| 153 | object_property_set_int(OBJECT(&s->ssp), "uart-dev", ASPEED_DEV_UART4, |
| 154 | &error_abort); |
| 155 | object_property_set_link(OBJECT(&s->ssp), "sram", |
| 156 | OBJECT(&psp->sram), &error_abort); |
| 157 | object_property_set_link(OBJECT(&s->ssp), "scu", |
| 158 | OBJECT(&s->ca35.scu), &error_abort); |
| 159 | object_property_set_link(OBJECT(&s->ssp), "scuio", |
| 160 | OBJECT(&psp->scuio), &error_abort); |
| 161 | object_property_set_link(OBJECT(&s->ssp), "fmc", |
| 162 | OBJECT(&psp->fmc), &error_abort); |
| 163 | if (!qdev_realize(DEVICE(&s->ssp), NULL, errp)) { |
| 164 | return false; |
| 165 | } |
| 166 | |
| 167 | return true; |
| 168 | } |
| 169 | |
| 170 | static bool ast2700fc_tsp_init(Ast2700FCState *s, AspeedSoCState *psp, |
| 171 | Error **errp) |
| 172 | { |
| 173 | s->tsp_sysclk = clock_new(OBJECT(s), "TSP_SYSCLK"); |
| 174 | clock_set_hz(s->tsp_sysclk, 200000000ULL); |
| 175 | |
| 176 | object_initialize_child(OBJECT(s), "tsp", &s->tsp, |
| 177 | TYPE_ASPEED27X0TSP_COPROCESSOR); |
| 178 | memory_region_init(&s->tsp_memory, OBJECT(&s->tsp), "tsp-memory", |
| 179 | UINT64_MAX); |
| 180 | |
| 181 | qdev_connect_clock_in(DEVICE(&s->tsp), "sysclk", s->tsp_sysclk); |
| 182 | object_property_set_link(OBJECT(&s->tsp), "memory", |
| 183 | OBJECT(&s->tsp_memory), &error_abort); |
| 184 | |
| 185 | object_property_set_link(OBJECT(&s->tsp), "uart", |
| 186 | OBJECT(&psp->uart[7]), &error_abort); |
| 187 | object_property_set_int(OBJECT(&s->tsp), "uart-dev", ASPEED_DEV_UART7, |
| 188 | &error_abort); |
| 189 | object_property_set_link(OBJECT(&s->tsp), "sram", |
| 190 | OBJECT(&psp->sram), &error_abort); |
| 191 | object_property_set_link(OBJECT(&s->tsp), "scu", |
| 192 | OBJECT(&s->ca35.scu), &error_abort); |
| 193 | object_property_set_link(OBJECT(&s->tsp), "scuio", |
| 194 | OBJECT(&psp->scuio), &error_abort); |
| 195 | object_property_set_link(OBJECT(&s->tsp), "fmc", |
| 196 | OBJECT(&psp->fmc), &error_abort); |
| 197 | if (!qdev_realize(DEVICE(&s->tsp), NULL, errp)) { |
| 198 | return false; |
| 199 | } |
| 200 | |
| 201 | return true; |
| 202 | } |
| 203 | |
| 204 | static void ast2700fc_init(MachineState *machine) |
| 205 | { |
| 206 | Ast2700FCState *s = AST2700FC(machine); |
| 207 | AspeedSoCState *psp; |
| 208 | |
| 209 | ast2700fc_ca35_init(machine, &error_abort); |
| 210 | |
| 211 | /* |
| 212 | * SSP and TSP use resources owned by the PSP SoC, such as UART, |
| 213 | * SRAM, SCU and SCUIO. Therefore the PSP SoC must be realized |
| 214 | * before the coprocessors are initialized. |
| 215 | */ |
| 216 | psp = ASPEED_SOC(&s->ca35); |
| 217 | ast2700fc_ssp_init(s, psp, &error_abort); |
| 218 | ast2700fc_tsp_init(s, psp, &error_abort); |
| 219 | } |
| 220 | |
| 221 | static void ast2700fc_class_init(ObjectClass *oc, const void *data) |
| 222 | { |
| 223 | MachineClass *mc = MACHINE_CLASS(oc); |
| 224 | |
| 225 | mc->desc = "ast2700 full core support"; |
| 226 | mc->init = ast2700fc_init; |
| 227 | mc->no_floppy = 1; |
| 228 | mc->no_cdrom = 1; |
| 229 | mc->min_cpus = mc->max_cpus = mc->default_cpus = 6; |
| 230 | } |
| 231 | |
| 232 | static const TypeInfo ast2700fc_types[] = { |
| 233 | { |
| 234 | .name = MACHINE_TYPE_NAME("ast2700fc"), |
| 235 | .parent = TYPE_MACHINE, |
| 236 | .class_init = ast2700fc_class_init, |
| 237 | .instance_size = sizeof(Ast2700FCState), |
| 238 | .interfaces = aarch64_machine_interfaces, |
| 239 | }, |
| 240 | }; |
| 241 | |
| 242 | DEFINE_TYPES(ast2700fc_types) |