xref: /qemu/hw/ppc/amigaone.c (revision d9656f860a38f83efc9710c515eab6a5b015134c)
1*d9656f86SBALATON Zoltan /*
2*d9656f86SBALATON Zoltan  * QEMU Eyetech AmigaOne/Mai Logic Teron emulation
3*d9656f86SBALATON Zoltan  *
4*d9656f86SBALATON Zoltan  * Copyright (c) 2023 BALATON Zoltan
5*d9656f86SBALATON Zoltan  *
6*d9656f86SBALATON Zoltan  * This work is licensed under the GNU GPL license version 2 or later.
7*d9656f86SBALATON Zoltan  *
8*d9656f86SBALATON Zoltan  */
9*d9656f86SBALATON Zoltan 
10*d9656f86SBALATON Zoltan #include "qemu/osdep.h"
11*d9656f86SBALATON Zoltan #include "qemu/units.h"
12*d9656f86SBALATON Zoltan #include "qemu/datadir.h"
13*d9656f86SBALATON Zoltan #include "qemu/log.h"
14*d9656f86SBALATON Zoltan #include "qemu/error-report.h"
15*d9656f86SBALATON Zoltan #include "qapi/error.h"
16*d9656f86SBALATON Zoltan #include "hw/ppc/ppc.h"
17*d9656f86SBALATON Zoltan #include "hw/boards.h"
18*d9656f86SBALATON Zoltan #include "hw/loader.h"
19*d9656f86SBALATON Zoltan #include "hw/pci-host/articia.h"
20*d9656f86SBALATON Zoltan #include "hw/isa/vt82c686.h"
21*d9656f86SBALATON Zoltan #include "hw/ide/pci.h"
22*d9656f86SBALATON Zoltan #include "hw/i2c/smbus_eeprom.h"
23*d9656f86SBALATON Zoltan #include "hw/ppc/ppc.h"
24*d9656f86SBALATON Zoltan #include "sysemu/qtest.h"
25*d9656f86SBALATON Zoltan #include "sysemu/reset.h"
26*d9656f86SBALATON Zoltan #include "kvm_ppc.h"
27*d9656f86SBALATON Zoltan 
28*d9656f86SBALATON Zoltan #define BUS_FREQ_HZ 100000000
29*d9656f86SBALATON Zoltan 
30*d9656f86SBALATON Zoltan /*
31*d9656f86SBALATON Zoltan  * Firmware binary available at
32*d9656f86SBALATON Zoltan  * https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28
33*d9656f86SBALATON Zoltan  * then "tail -c 524288 updater.image >u-boot-amigaone.bin"
34*d9656f86SBALATON Zoltan  *
35*d9656f86SBALATON Zoltan  * BIOS emulator in firmware cannot run QEMU vgabios and hangs on it, use
36*d9656f86SBALATON Zoltan  * -device VGA,romfile=VGABIOS-lgpl-latest.bin
37*d9656f86SBALATON Zoltan  * from http://www.nongnu.org/vgabios/ instead.
38*d9656f86SBALATON Zoltan  */
39*d9656f86SBALATON Zoltan #define PROM_FILENAME "u-boot-amigaone.bin"
40*d9656f86SBALATON Zoltan #define PROM_ADDR 0xfff00000
41*d9656f86SBALATON Zoltan #define PROM_SIZE (512 * KiB)
42*d9656f86SBALATON Zoltan 
43*d9656f86SBALATON Zoltan static void amigaone_cpu_reset(void *opaque)
44*d9656f86SBALATON Zoltan {
45*d9656f86SBALATON Zoltan     PowerPCCPU *cpu = opaque;
46*d9656f86SBALATON Zoltan 
47*d9656f86SBALATON Zoltan     cpu_reset(CPU(cpu));
48*d9656f86SBALATON Zoltan     cpu_ppc_tb_reset(&cpu->env);
49*d9656f86SBALATON Zoltan }
50*d9656f86SBALATON Zoltan 
51*d9656f86SBALATON Zoltan static void fix_spd_data(uint8_t *spd)
52*d9656f86SBALATON Zoltan {
53*d9656f86SBALATON Zoltan     uint32_t bank_size = 4 * MiB * spd[31];
54*d9656f86SBALATON Zoltan     uint32_t rows = bank_size / spd[13] / spd[17];
55*d9656f86SBALATON Zoltan     spd[3] = ctz32(rows) - spd[4];
56*d9656f86SBALATON Zoltan }
57*d9656f86SBALATON Zoltan 
58*d9656f86SBALATON Zoltan static void amigaone_init(MachineState *machine)
59*d9656f86SBALATON Zoltan {
60*d9656f86SBALATON Zoltan     PowerPCCPU *cpu;
61*d9656f86SBALATON Zoltan     CPUPPCState *env;
62*d9656f86SBALATON Zoltan     MemoryRegion *rom, *pci_mem, *mr;
63*d9656f86SBALATON Zoltan     const char *fwname = machine->firmware ?: PROM_FILENAME;
64*d9656f86SBALATON Zoltan     char *filename;
65*d9656f86SBALATON Zoltan     ssize_t sz;
66*d9656f86SBALATON Zoltan     PCIBus *pci_bus;
67*d9656f86SBALATON Zoltan     Object *via;
68*d9656f86SBALATON Zoltan     DeviceState *dev;
69*d9656f86SBALATON Zoltan     I2CBus *i2c_bus;
70*d9656f86SBALATON Zoltan     uint8_t *spd_data;
71*d9656f86SBALATON Zoltan     int i;
72*d9656f86SBALATON Zoltan 
73*d9656f86SBALATON Zoltan     /* init CPU */
74*d9656f86SBALATON Zoltan     cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
75*d9656f86SBALATON Zoltan     env = &cpu->env;
76*d9656f86SBALATON Zoltan     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
77*d9656f86SBALATON Zoltan         error_report("Incompatible CPU, only 6xx bus supported");
78*d9656f86SBALATON Zoltan         exit(1);
79*d9656f86SBALATON Zoltan     }
80*d9656f86SBALATON Zoltan     cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4);
81*d9656f86SBALATON Zoltan     qemu_register_reset(amigaone_cpu_reset, cpu);
82*d9656f86SBALATON Zoltan 
83*d9656f86SBALATON Zoltan     /* RAM */
84*d9656f86SBALATON Zoltan     if (machine->ram_size > 2 * GiB) {
85*d9656f86SBALATON Zoltan         error_report("RAM size more than 2 GiB is not supported");
86*d9656f86SBALATON Zoltan         exit(1);
87*d9656f86SBALATON Zoltan     }
88*d9656f86SBALATON Zoltan     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
89*d9656f86SBALATON Zoltan     if (machine->ram_size < 1 * GiB + 32 * KiB) {
90*d9656f86SBALATON Zoltan         /* Firmware uses this area for startup */
91*d9656f86SBALATON Zoltan         mr = g_new(MemoryRegion, 1);
92*d9656f86SBALATON Zoltan         memory_region_init_ram(mr, NULL, "init-cache", 32 * KiB, &error_fatal);
93*d9656f86SBALATON Zoltan         memory_region_add_subregion(get_system_memory(), 0x40000000, mr);
94*d9656f86SBALATON Zoltan     }
95*d9656f86SBALATON Zoltan 
96*d9656f86SBALATON Zoltan     /* allocate and load firmware */
97*d9656f86SBALATON Zoltan     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, fwname);
98*d9656f86SBALATON Zoltan     if (filename) {
99*d9656f86SBALATON Zoltan         rom = g_new(MemoryRegion, 1);
100*d9656f86SBALATON Zoltan         memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal);
101*d9656f86SBALATON Zoltan         memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom);
102*d9656f86SBALATON Zoltan         sz = load_image_targphys(filename, PROM_ADDR, PROM_SIZE);
103*d9656f86SBALATON Zoltan         if (sz <= 0 || sz > PROM_SIZE) {
104*d9656f86SBALATON Zoltan             error_report("Could not load firmware '%s'", filename);
105*d9656f86SBALATON Zoltan             exit(1);
106*d9656f86SBALATON Zoltan         }
107*d9656f86SBALATON Zoltan         g_free(filename);
108*d9656f86SBALATON Zoltan     } else if (!qtest_enabled()) {
109*d9656f86SBALATON Zoltan         error_report("Could not find firmware '%s'", fwname);
110*d9656f86SBALATON Zoltan         exit(1);
111*d9656f86SBALATON Zoltan     }
112*d9656f86SBALATON Zoltan 
113*d9656f86SBALATON Zoltan     /* Articia S */
114*d9656f86SBALATON Zoltan     dev = sysbus_create_simple(TYPE_ARTICIA, 0xfe000000, NULL);
115*d9656f86SBALATON Zoltan 
116*d9656f86SBALATON Zoltan     i2c_bus = I2C_BUS(qdev_get_child_bus(dev, "smbus"));
117*d9656f86SBALATON Zoltan     if (machine->ram_size > 512 * MiB) {
118*d9656f86SBALATON Zoltan         spd_data = spd_data_generate(SDR, machine->ram_size / 2);
119*d9656f86SBALATON Zoltan     } else {
120*d9656f86SBALATON Zoltan         spd_data = spd_data_generate(SDR, machine->ram_size);
121*d9656f86SBALATON Zoltan     }
122*d9656f86SBALATON Zoltan     fix_spd_data(spd_data);
123*d9656f86SBALATON Zoltan     smbus_eeprom_init_one(i2c_bus, 0x51, spd_data);
124*d9656f86SBALATON Zoltan     if (machine->ram_size > 512 * MiB) {
125*d9656f86SBALATON Zoltan         smbus_eeprom_init_one(i2c_bus, 0x52, spd_data);
126*d9656f86SBALATON Zoltan     }
127*d9656f86SBALATON Zoltan 
128*d9656f86SBALATON Zoltan     pci_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
129*d9656f86SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
130*d9656f86SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(dev), "pci-mem-low", pci_mem,
131*d9656f86SBALATON Zoltan                              0, 0x1000000);
132*d9656f86SBALATON Zoltan     memory_region_add_subregion(get_system_memory(), 0xfd000000, mr);
133*d9656f86SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
134*d9656f86SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(dev), "pci-mem-high", pci_mem,
135*d9656f86SBALATON Zoltan                              0x80000000, 0x7d000000);
136*d9656f86SBALATON Zoltan     memory_region_add_subregion(get_system_memory(), 0x80000000, mr);
137*d9656f86SBALATON Zoltan     pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
138*d9656f86SBALATON Zoltan 
139*d9656f86SBALATON Zoltan     /* VIA VT82c686B South Bridge (multifunction PCI device) */
140*d9656f86SBALATON Zoltan     via = OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(7, 0),
141*d9656f86SBALATON Zoltan                                                  TYPE_VT82C686B_ISA));
142*d9656f86SBALATON Zoltan     object_property_add_alias(OBJECT(machine), "rtc-time",
143*d9656f86SBALATON Zoltan                               object_resolve_path_component(via, "rtc"),
144*d9656f86SBALATON Zoltan                               "date");
145*d9656f86SBALATON Zoltan     qdev_connect_gpio_out(DEVICE(via), 0,
146*d9656f86SBALATON Zoltan                           qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT));
147*d9656f86SBALATON Zoltan     for (i = 0; i < PCI_NUM_PINS; i++) {
148*d9656f86SBALATON Zoltan         qdev_connect_gpio_out(dev, i, qdev_get_gpio_in_named(DEVICE(via),
149*d9656f86SBALATON Zoltan                                                              "pirq", i));
150*d9656f86SBALATON Zoltan     }
151*d9656f86SBALATON Zoltan     pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, "ide")));
152*d9656f86SBALATON Zoltan     pci_vga_init(pci_bus);
153*d9656f86SBALATON Zoltan }
154*d9656f86SBALATON Zoltan 
155*d9656f86SBALATON Zoltan static void amigaone_machine_init(MachineClass *mc)
156*d9656f86SBALATON Zoltan {
157*d9656f86SBALATON Zoltan     mc->desc = "Eyetech AmigaOne/Mai Logic Teron";
158*d9656f86SBALATON Zoltan     mc->init = amigaone_init;
159*d9656f86SBALATON Zoltan     mc->block_default_type = IF_IDE;
160*d9656f86SBALATON Zoltan     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7457_v1.2");
161*d9656f86SBALATON Zoltan     mc->default_display = "std";
162*d9656f86SBALATON Zoltan     mc->default_ram_id = "ram";
163*d9656f86SBALATON Zoltan     mc->default_ram_size = 512 * MiB;
164*d9656f86SBALATON Zoltan }
165*d9656f86SBALATON Zoltan 
166*d9656f86SBALATON Zoltan DEFINE_MACHINE("amigaone", amigaone_machine_init)
167