mirror of
https://github.com/qemu/qemu.git
synced 2026-02-14 21:32:50 +00:00
hw/ppc/pegasos2: Add VOF support for pegasos1
When running without firmware ROM using Virtual Open Firmware we need to do some hardware initialisation and provide the device tree as the machine firmware would normally do. Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Link: https://lore.kernel.org/qemu-devel/d2d7f173dbd436b47382f384d5a93eb7e713424e.1761176219.git.balaton@eik.bme.hu Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
This commit is contained in:
committed by
Harsh Prateek Bora
parent
d3a16439c3
commit
3c21f9dfcf
@@ -1652,6 +1652,7 @@ F: hw/ppc/pegasos2.c
|
||||
F: hw/pci-host/mv64361.c
|
||||
F: hw/pci-host/mv643xx.h
|
||||
F: include/hw/pci-host/mv64361.h
|
||||
F: pc-bios/dtb/pegasos[12].dt[sb]
|
||||
|
||||
amigaone
|
||||
M: BALATON Zoltan <balaton@eik.bme.hu>
|
||||
|
||||
@@ -84,6 +84,7 @@ struct PegasosMachineState {
|
||||
uint64_t initrd_size;
|
||||
};
|
||||
|
||||
static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size);
|
||||
static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size);
|
||||
|
||||
static void pegasos_cpu_reset(void *opaque)
|
||||
@@ -314,6 +315,82 @@ static void pegasos_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
static void pegasos_superio_write(uint8_t addr, uint8_t val)
|
||||
{
|
||||
cpu_physical_memory_write(0xfe0003f0, &addr, 1);
|
||||
cpu_physical_memory_write(0xfe0003f1, &val, 1);
|
||||
}
|
||||
|
||||
static void pegasos1_pci_config_write(PegasosMachineState *pm, int bus,
|
||||
uint32_t addr, uint32_t len, uint32_t val)
|
||||
{
|
||||
addr |= BIT(31);
|
||||
cpu_physical_memory_write(0xfec00cf8, &addr, 4);
|
||||
cpu_physical_memory_write(0xfee00cfc, &val, len);
|
||||
}
|
||||
|
||||
static void pegasos1_chipset_reset(PegasosMachineState *pm)
|
||||
{
|
||||
uint8_t elcr = 0x2e;
|
||||
cpu_physical_memory_write(0xfe0004d1, &elcr, sizeof(elcr));
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, PCI_COMMAND, 2, PCI_COMMAND_IO |
|
||||
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x9);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
0x50, 1, 0x6);
|
||||
pegasos_superio_write(0xf4, 0xbe);
|
||||
pegasos_superio_write(0xf6, 0xef);
|
||||
pegasos_superio_write(0xf7, 0xfc);
|
||||
pegasos_superio_write(0xf2, 0x14);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
0x51, 1, 0x3d);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
0x55, 1, 0x90);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
0x56, 1, 0x99);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 0) << 8) |
|
||||
0x57, 1, 0x90);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x10e);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
|
||||
PCI_CLASS_PROG, 1, 0xf);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
|
||||
0x40, 1, 0xb);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
|
||||
0x50, 4, 0x17171717);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 1) << 8) |
|
||||
PCI_COMMAND, 2, 0x87);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x409);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 2) << 8) |
|
||||
PCI_COMMAND, 2, 0x7);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x409);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 3) << 8) |
|
||||
PCI_COMMAND, 2, 0x7);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x9);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
|
||||
0x48, 4, 0x2001);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
|
||||
0x41, 1, 0);
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 4) << 8) |
|
||||
0x90, 4, 0x1000);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 5) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x309);
|
||||
|
||||
pegasos1_pci_config_write(pm, 0, (PCI_DEVFN(7, 6) << 8) |
|
||||
PCI_INTERRUPT_LINE, 2, 0x309);
|
||||
}
|
||||
|
||||
static uint32_t pegasos2_mv_reg_read(PegasosMachineState *pm,
|
||||
uint32_t addr, uint32_t len)
|
||||
{
|
||||
@@ -357,12 +434,6 @@ static void pegasos2_pci_config_write(PegasosMachineState *pm, int bus,
|
||||
pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
|
||||
}
|
||||
|
||||
static void pegasos2_superio_write(uint8_t addr, uint8_t val)
|
||||
{
|
||||
cpu_physical_memory_write(0xfe0003f0, &addr, 1);
|
||||
cpu_physical_memory_write(0xfe0003f1, &val, 1);
|
||||
}
|
||||
|
||||
static void pegasos2_chipset_reset(PegasosMachineState *pm)
|
||||
{
|
||||
pegasos2_mv_reg_write(pm, 0, 4, 0x28020ff);
|
||||
@@ -379,10 +450,10 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
|
||||
PCI_INTERRUPT_LINE, 2, 0x9);
|
||||
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
|
||||
0x50, 1, 0x6);
|
||||
pegasos2_superio_write(0xf4, 0xbe);
|
||||
pegasos2_superio_write(0xf6, 0xef);
|
||||
pegasos2_superio_write(0xf7, 0xfc);
|
||||
pegasos2_superio_write(0xf2, 0x14);
|
||||
pegasos_superio_write(0xf4, 0xbe);
|
||||
pegasos_superio_write(0xf6, 0xef);
|
||||
pegasos_superio_write(0xf7, 0xfc);
|
||||
pegasos_superio_write(0xf2, 0x14);
|
||||
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
|
||||
0x50, 1, 0x2);
|
||||
pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) |
|
||||
@@ -432,7 +503,7 @@ static void pegasos2_chipset_reset(PegasosMachineState *pm)
|
||||
static void pegasos_machine_reset(MachineState *machine, ResetType type)
|
||||
{
|
||||
PegasosMachineState *pm = PEGASOS_MACHINE(machine);
|
||||
void *fdt;
|
||||
void *fdt = NULL;
|
||||
uint32_t c[2];
|
||||
uint64_t d[2];
|
||||
int sz;
|
||||
@@ -440,13 +511,22 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type)
|
||||
qemu_devices_reset(type);
|
||||
if (!pm->vof) {
|
||||
return; /* Firmware should set up machine so nothing to do */
|
||||
} else if (pm->type == PEGASOS1) {
|
||||
error_report("VOF is not supported by this machine");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Otherwise, set up devices that board firmware would normally do */
|
||||
pegasos2_chipset_reset(pm);
|
||||
switch (pm->type) {
|
||||
case PEGASOS1:
|
||||
pegasos1_chipset_reset(pm);
|
||||
fdt = pegasos1_build_fdt(pm, &sz);
|
||||
break;
|
||||
case PEGASOS2:
|
||||
pegasos2_chipset_reset(pm);
|
||||
fdt = pegasos2_build_fdt(pm, &sz);
|
||||
break;
|
||||
}
|
||||
if (!fdt) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Device tree and VOF set up */
|
||||
vof_init(pm->vof, machine->ram_size, &error_fatal);
|
||||
@@ -465,11 +545,6 @@ static void pegasos_machine_reset(MachineState *machine, ResetType type)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fdt = pegasos2_build_fdt(pm, &sz);
|
||||
if (!fdt) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Set memory size */
|
||||
c[0] = 0;
|
||||
c[1] = cpu_to_be32(machine->ram_size);
|
||||
@@ -761,6 +836,8 @@ static struct {
|
||||
const char *name;
|
||||
void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi);
|
||||
} device_map[] = {
|
||||
{ "pci10cc,660", "host", NULL },
|
||||
{ "pci10cc,661", "host", NULL },
|
||||
{ "pci11ab,6460", "host", NULL },
|
||||
{ "pci1106,571", "ide", dt_ide },
|
||||
{ "pci1106,3044", "firewire", NULL },
|
||||
@@ -846,7 +923,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque)
|
||||
qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts",
|
||||
pci_get_byte(&d->config[PCI_INTERRUPT_PIN]));
|
||||
}
|
||||
/* Pegasos2 firmware has subsystem-id amd subsystem-vendor-id swapped */
|
||||
/* Pegasos firmware has subsystem-id and subsystem-vendor-id swapped */
|
||||
qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-vendor-id",
|
||||
pci_get_word(&d->config[PCI_SUBSYSTEM_ID]));
|
||||
qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-id",
|
||||
@@ -934,6 +1011,27 @@ static void *load_dtb(const char *filename, int *fdt_size)
|
||||
return fdt;
|
||||
}
|
||||
|
||||
static void *pegasos1_build_fdt(PegasosMachineState *pm, int *fdt_size)
|
||||
{
|
||||
FDTInfo fi;
|
||||
PCIBus *pci_bus;
|
||||
void *fdt = load_dtb("pegasos1.dtb", fdt_size);
|
||||
|
||||
if (!fdt) {
|
||||
return NULL;
|
||||
}
|
||||
qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos");
|
||||
|
||||
add_cpu_info(fdt, pm->cpu, pm->bus_freq_hz);
|
||||
|
||||
fi.fdt = fdt;
|
||||
fi.path = "/pci@80000000";
|
||||
pci_bus = PCI_BUS(qdev_get_child_bus(pm->nb, "pci.0"));
|
||||
pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi);
|
||||
|
||||
return fdt;
|
||||
}
|
||||
|
||||
static void *pegasos2_build_fdt(PegasosMachineState *pm, int *fdt_size)
|
||||
{
|
||||
FDTInfo fi;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
dtbs = [
|
||||
'bamboo.dtb',
|
||||
'canyonlands.dtb',
|
||||
'pegasos1.dtb',
|
||||
'pegasos2.dtb',
|
||||
'petalogix-ml605.dtb',
|
||||
'petalogix-s3adsp1800.dtb',
|
||||
|
||||
BIN
pc-bios/dtb/pegasos1.dtb
Normal file
BIN
pc-bios/dtb/pegasos1.dtb
Normal file
Binary file not shown.
125
pc-bios/dtb/pegasos1.dts
Normal file
125
pc-bios/dtb/pegasos1.dts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* QEMU Pegasos1 Device Tree Source
|
||||
*
|
||||
* Copyright 2025 BALATON Zoltan
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This is partial source, more info will be filled in by board code.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
device_type = "chrp";
|
||||
model = "Pegasos";
|
||||
revision = "1A";
|
||||
CODEGEN,vendor = "bplan GmbH";
|
||||
CODEGEN,board = "Pegasos";
|
||||
CODEGEN,description = "Pegasos CHRP PowerPC System";
|
||||
|
||||
openprom {
|
||||
model = "Pegasos,0.1b123";
|
||||
};
|
||||
|
||||
chosen {
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0 0>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#cpus = <1>;
|
||||
};
|
||||
|
||||
failsafe {
|
||||
device_type = "serial";
|
||||
};
|
||||
|
||||
pci@80000000 {
|
||||
device_type = "pci";
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
clock-frequency = <33333333>;
|
||||
8259-interrupt-acknowledge = <0xfef00000>;
|
||||
reg = <0x80000000 0x7f000000>;
|
||||
ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00800000
|
||||
0x02000000 0 0x80000000 0x80000000 0 0x7d000000
|
||||
0x02000000 0 0xfd000000 0xfd000000 0 0x01000000>;
|
||||
bus-range = <0 0>;
|
||||
|
||||
isa@7 {
|
||||
vendor-id = <0x1106>;
|
||||
device-id = <0x8231>;
|
||||
revision-id = <0x10>;
|
||||
class-code = <0x60100>;
|
||||
/* Pegasos firmware has subsystem-id and */
|
||||
/* subsystem-vendor-id swapped */
|
||||
subsystem-id = <0x1af4>;
|
||||
subsystem-vendor-id = <0x1100>;
|
||||
reg = <0x3800 0 0 0 0>;
|
||||
device_type = "isa";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
eisa-slots = <0>;
|
||||
clock-frequency = <8333333>;
|
||||
slot-names = <0>;
|
||||
|
||||
serial@i2f8 {
|
||||
device_type = "serial";
|
||||
reg = <1 0x2f8 8>;
|
||||
interrupts = <3 0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
8042@i60 {
|
||||
device_type = "";
|
||||
reg = <1 0x60 5>;
|
||||
clock-frequency = <0>;
|
||||
interrupt-controller = "";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
};
|
||||
|
||||
keyboard@i60 {
|
||||
device_type = "keyboard";
|
||||
reg = <1 0x60 5>;
|
||||
interrupts = <1 0>;
|
||||
};
|
||||
|
||||
rtc@i70 {
|
||||
device_type = "rtc";
|
||||
reg = <1 0x70 2>;
|
||||
interrupts = <8 0>;
|
||||
clock-frequency = <0>;
|
||||
compatible = "ds1385-rtc";
|
||||
};
|
||||
|
||||
timer@i40 {
|
||||
device_type = "timer";
|
||||
reg = <1 0x40 8>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
fdc@i3f0 {
|
||||
device_type = "fdc";
|
||||
reg = <1 0x3f0 8>;
|
||||
interrupts = <6 0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
lpt@i3bc {
|
||||
device_type = "lpt";
|
||||
reg = <1 0x3bc 8>;
|
||||
interrupts = <7 0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user