153018216SPaolo Bonzini /*
253018216SPaolo Bonzini * QEMU PowerPC 440 Bamboo board emulation
353018216SPaolo Bonzini *
453018216SPaolo Bonzini * Copyright 2007 IBM Corporation.
553018216SPaolo Bonzini * Authors:
653018216SPaolo Bonzini * Jerone Young <jyoung5@us.ibm.com>
753018216SPaolo Bonzini * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
853018216SPaolo Bonzini * Hollis Blanchard <hollisb@us.ibm.com>
953018216SPaolo Bonzini *
1053018216SPaolo Bonzini * This work is licensed under the GNU GPL license version 2 or later.
1153018216SPaolo Bonzini *
1253018216SPaolo Bonzini */
1353018216SPaolo Bonzini
140d75590dSPeter Maydell #include "qemu/osdep.h"
15ab3dd749SPhilippe Mathieu-Daudé #include "qemu/units.h"
162c65db5eSPaolo Bonzini #include "qemu/datadir.h"
1764b47457Sthuth@redhat.com #include "qemu/error-report.h"
1874781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h"
1953018216SPaolo Bonzini #include "net/net.h"
2053018216SPaolo Bonzini #include "hw/pci/pci.h"
2153018216SPaolo Bonzini #include "hw/boards.h"
2253018216SPaolo Bonzini #include "sysemu/kvm.h"
2353018216SPaolo Bonzini #include "sysemu/device_tree.h"
2453018216SPaolo Bonzini #include "hw/loader.h"
2553018216SPaolo Bonzini #include "elf.h"
267e6b5497SBernhard Beschow #include "hw/char/serial-mm.h"
270d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
284d641f36SPhilippe Mathieu-Daudé #include "hw/pci-host/ppc4xx.h"
2953018216SPaolo Bonzini #include "sysemu/sysemu.h"
3071e8a915SMarkus Armbruster #include "sysemu/reset.h"
3153018216SPaolo Bonzini #include "hw/sysbus.h"
320270d74eSPeter Maydell #include "hw/intc/ppc-uic.h"
330270d74eSPeter Maydell #include "hw/qdev-properties.h"
340270d74eSPeter Maydell #include "qapi/error.h"
3553018216SPaolo Bonzini
368d42c851SDaniel Henrique Barboza #include <libfdt.h>
378d42c851SDaniel Henrique Barboza
3853018216SPaolo Bonzini #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
3953018216SPaolo Bonzini
4053018216SPaolo Bonzini /* from u-boot */
4153018216SPaolo Bonzini #define KERNEL_ADDR 0x1000000
4253018216SPaolo Bonzini #define FDT_ADDR 0x1800000
4353018216SPaolo Bonzini #define RAMDISK_ADDR 0x1900000
4453018216SPaolo Bonzini
4553018216SPaolo Bonzini #define PPC440EP_PCI_CONFIG 0xeec00000
4653018216SPaolo Bonzini #define PPC440EP_PCI_INTACK 0xeed00000
4753018216SPaolo Bonzini #define PPC440EP_PCI_SPECIAL 0xeed00000
4853018216SPaolo Bonzini #define PPC440EP_PCI_REGS 0xef400000
4953018216SPaolo Bonzini #define PPC440EP_PCI_IO 0xe8000000
5053018216SPaolo Bonzini #define PPC440EP_PCI_IOLEN 0x00010000
5153018216SPaolo Bonzini
5253018216SPaolo Bonzini static hwaddr entry;
5353018216SPaolo Bonzini
bamboo_load_device_tree(MachineState * machine,hwaddr addr,hwaddr initrd_base,hwaddr initrd_size)548d42c851SDaniel Henrique Barboza static int bamboo_load_device_tree(MachineState *machine,
558d42c851SDaniel Henrique Barboza hwaddr addr,
5653018216SPaolo Bonzini hwaddr initrd_base,
578d42c851SDaniel Henrique Barboza hwaddr initrd_size)
5853018216SPaolo Bonzini {
5953018216SPaolo Bonzini int ret = -1;
608d42c851SDaniel Henrique Barboza uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
6153018216SPaolo Bonzini char *filename;
6253018216SPaolo Bonzini int fdt_size;
6353018216SPaolo Bonzini void *fdt;
6453018216SPaolo Bonzini uint32_t tb_freq = 400000000;
6553018216SPaolo Bonzini uint32_t clock_freq = 400000000;
6653018216SPaolo Bonzini
6753018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
6853018216SPaolo Bonzini if (!filename) {
69400431efSDaniel Henrique Barboza return -1;
7053018216SPaolo Bonzini }
7153018216SPaolo Bonzini fdt = load_device_tree(filename, &fdt_size);
7253018216SPaolo Bonzini g_free(filename);
7353018216SPaolo Bonzini if (fdt == NULL) {
74400431efSDaniel Henrique Barboza return -1;
7553018216SPaolo Bonzini }
7653018216SPaolo Bonzini
7753018216SPaolo Bonzini /* Manipulate device tree in memory. */
7853018216SPaolo Bonzini
795a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
8053018216SPaolo Bonzini sizeof(mem_reg_property));
8195e22932SBALATON Zoltan if (ret < 0) {
8253018216SPaolo Bonzini fprintf(stderr, "couldn't set /memory/reg\n");
8395e22932SBALATON Zoltan }
845a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
8553018216SPaolo Bonzini initrd_base);
8695e22932SBALATON Zoltan if (ret < 0) {
8753018216SPaolo Bonzini fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
8895e22932SBALATON Zoltan }
895a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
9053018216SPaolo Bonzini (initrd_base + initrd_size));
9195e22932SBALATON Zoltan if (ret < 0) {
9253018216SPaolo Bonzini fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
9395e22932SBALATON Zoltan }
945a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
958d42c851SDaniel Henrique Barboza machine->kernel_cmdline);
9695e22932SBALATON Zoltan if (ret < 0) {
9753018216SPaolo Bonzini fprintf(stderr, "couldn't set /chosen/bootargs\n");
9895e22932SBALATON Zoltan }
9953018216SPaolo Bonzini
1005a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
10153018216SPaolo Bonzini clock_freq);
1025a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
10353018216SPaolo Bonzini tb_freq);
10453018216SPaolo Bonzini
105fe1479aaSMichael S. Tsirkin rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
1068d42c851SDaniel Henrique Barboza
1078d42c851SDaniel Henrique Barboza /* Set ms->fdt for 'dumpdtb' QMP/HMP command */
1088d42c851SDaniel Henrique Barboza machine->fdt = fdt;
1098d42c851SDaniel Henrique Barboza
110fe1479aaSMichael S. Tsirkin return 0;
11153018216SPaolo Bonzini }
11253018216SPaolo Bonzini
main_cpu_reset(void * opaque)11353018216SPaolo Bonzini static void main_cpu_reset(void *opaque)
11453018216SPaolo Bonzini {
11553018216SPaolo Bonzini PowerPCCPU *cpu = opaque;
11653018216SPaolo Bonzini CPUPPCState *env = &cpu->env;
11753018216SPaolo Bonzini
11853018216SPaolo Bonzini cpu_reset(CPU(cpu));
119ab3dd749SPhilippe Mathieu-Daudé env->gpr[1] = (16 * MiB) - 8;
12053018216SPaolo Bonzini env->gpr[3] = FDT_ADDR;
12153018216SPaolo Bonzini env->nip = entry;
12253018216SPaolo Bonzini
123*afff8800SBALATON Zoltan /* Create a mapping spanning the 32bit addr space. */
124*afff8800SBALATON Zoltan booke_set_tlb(&env->tlb.tlbe[0], 0, 0, 1U << 31);
125*afff8800SBALATON Zoltan booke_set_tlb(&env->tlb.tlbe[1], 0x80000000, 0x80000000, 1U << 31);
12653018216SPaolo Bonzini }
12753018216SPaolo Bonzini
bamboo_init(MachineState * machine)1283ef96221SMarcel Apfelbaum static void bamboo_init(MachineState *machine)
12953018216SPaolo Bonzini {
1303ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename;
1313ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename;
132053b7086SThomas Huth MachineClass *mc = MACHINE_GET_CLASS(machine);
13353018216SPaolo Bonzini unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
13453018216SPaolo Bonzini MemoryRegion *address_space_mem = get_system_memory();
13568501502SPaolo Bonzini MemoryRegion *isa = g_new(MemoryRegion, 1);
13653018216SPaolo Bonzini PCIBus *pcibus;
13753018216SPaolo Bonzini PowerPCCPU *cpu;
13853018216SPaolo Bonzini CPUPPCState *env;
13953018216SPaolo Bonzini target_long initrd_size = 0;
14053018216SPaolo Bonzini DeviceState *dev;
1410270d74eSPeter Maydell DeviceState *uicdev;
1420270d74eSPeter Maydell SysBusDevice *uicsbd;
14353018216SPaolo Bonzini int success;
14453018216SPaolo Bonzini
14574b2fd63SCédric Le Goater if (kvm_enabled()) {
14674b2fd63SCédric Le Goater error_report("machine %s does not support the KVM accelerator",
14774b2fd63SCédric Le Goater MACHINE_GET_CLASS(machine)->name);
14874b2fd63SCédric Le Goater exit(EXIT_FAILURE);
14974b2fd63SCédric Le Goater }
15074b2fd63SCédric Le Goater
151376d7a2aSIgor Mammedov cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
15253018216SPaolo Bonzini env = &cpu->env;
15353018216SPaolo Bonzini
15400469dc3SValentin Plotkin if (env->mmu_model != POWERPC_MMU_BOOKE) {
1556f76b817SAlistair Francis error_report("MMU model %i not supported by this machine",
15600469dc3SValentin Plotkin env->mmu_model);
15700469dc3SValentin Plotkin exit(1);
15800469dc3SValentin Plotkin }
15900469dc3SValentin Plotkin
16053018216SPaolo Bonzini qemu_register_reset(main_cpu_reset, cpu);
16153018216SPaolo Bonzini ppc_booke_timers_init(cpu, 400000000, 0);
16253018216SPaolo Bonzini ppc_dcr_init(env, NULL, NULL);
16353018216SPaolo Bonzini
16453018216SPaolo Bonzini /* interrupt controller */
1650270d74eSPeter Maydell uicdev = qdev_new(TYPE_PPC_UIC);
166a55b2136SBALATON Zoltan ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal);
167a55b2136SBALATON Zoltan object_unref(OBJECT(uicdev));
1680270d74eSPeter Maydell uicsbd = SYS_BUS_DEVICE(uicdev);
1690270d74eSPeter Maydell sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT,
17047b60fc6SCédric Le Goater qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT));
1710270d74eSPeter Maydell sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT,
17247b60fc6SCédric Le Goater qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
17353018216SPaolo Bonzini
17453018216SPaolo Bonzini /* SDRAM controller */
1754fc30e15SBALATON Zoltan dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
1764fc30e15SBALATON Zoltan object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
1774fc30e15SBALATON Zoltan &error_abort);
1784fc30e15SBALATON Zoltan ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
1794fc30e15SBALATON Zoltan object_unref(OBJECT(dev));
18053018216SPaolo Bonzini /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
1814fc30e15SBALATON Zoltan sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
18268b9a2e3SBALATON Zoltan /* Enable SDRAM memory regions, this should be done by the firmware */
1831e545fbcSBALATON Zoltan ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
18453018216SPaolo Bonzini
18553018216SPaolo Bonzini /* PCI */
186e75a951bSBALATON Zoltan dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST, PPC440EP_PCI_CONFIG,
1870270d74eSPeter Maydell qdev_get_gpio_in(uicdev, pci_irq_nrs[0]),
1880270d74eSPeter Maydell qdev_get_gpio_in(uicdev, pci_irq_nrs[1]),
1890270d74eSPeter Maydell qdev_get_gpio_in(uicdev, pci_irq_nrs[2]),
1900270d74eSPeter Maydell qdev_get_gpio_in(uicdev, pci_irq_nrs[3]),
19153018216SPaolo Bonzini NULL);
19253018216SPaolo Bonzini pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
19353018216SPaolo Bonzini if (!pcibus) {
1946f76b817SAlistair Francis error_report("couldn't create PCI controller");
19553018216SPaolo Bonzini exit(1);
19653018216SPaolo Bonzini }
19753018216SPaolo Bonzini
19868501502SPaolo Bonzini memory_region_init_alias(isa, NULL, "isa_mmio",
19968501502SPaolo Bonzini get_system_io(), 0, PPC440EP_PCI_IOLEN);
20068501502SPaolo Bonzini memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa);
20153018216SPaolo Bonzini
2029bca0edbSPeter Maydell if (serial_hd(0) != NULL) {
2030270d74eSPeter Maydell serial_mm_init(address_space_mem, 0xef600300, 0,
2040270d74eSPeter Maydell qdev_get_gpio_in(uicdev, 0),
2059bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
20653018216SPaolo Bonzini DEVICE_BIG_ENDIAN);
20753018216SPaolo Bonzini }
2089bca0edbSPeter Maydell if (serial_hd(1) != NULL) {
2090270d74eSPeter Maydell serial_mm_init(address_space_mem, 0xef600400, 0,
2100270d74eSPeter Maydell qdev_get_gpio_in(uicdev, 1),
2119bca0edbSPeter Maydell PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
21253018216SPaolo Bonzini DEVICE_BIG_ENDIAN);
21353018216SPaolo Bonzini }
21453018216SPaolo Bonzini
21553018216SPaolo Bonzini if (pcibus) {
21695e22932SBALATON Zoltan /*
21795e22932SBALATON Zoltan * There are no PCI NICs on the Bamboo board, but there are
21895e22932SBALATON Zoltan * PCI slots, so we can pick whatever default model we want.
21995e22932SBALATON Zoltan */
22036b6968dSDavid Woodhouse pci_init_nic_devices(pcibus, mc->default_nic);
22153018216SPaolo Bonzini }
22253018216SPaolo Bonzini
22353018216SPaolo Bonzini /* Load kernel. */
22453018216SPaolo Bonzini if (kernel_filename) {
225617160c9SBALATON Zoltan hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
22625bda50aSMax Filippov success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
22725bda50aSMax Filippov NULL, NULL);
22853018216SPaolo Bonzini if (success < 0) {
229617160c9SBALATON Zoltan uint64_t elf_entry;
2304366e1dbSLiam Merwick success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
231617160c9SBALATON Zoltan NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
23253018216SPaolo Bonzini entry = elf_entry;
23353018216SPaolo Bonzini }
23453018216SPaolo Bonzini /* XXX try again as binary */
23553018216SPaolo Bonzini if (success < 0) {
2366f76b817SAlistair Francis error_report("could not load kernel '%s'", kernel_filename);
23753018216SPaolo Bonzini exit(1);
23853018216SPaolo Bonzini }
23953018216SPaolo Bonzini }
24053018216SPaolo Bonzini
24153018216SPaolo Bonzini /* Load initrd. */
24253018216SPaolo Bonzini if (initrd_filename) {
24353018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
244a0258e4aSIgor Mammedov machine->ram_size - RAMDISK_ADDR);
24553018216SPaolo Bonzini
24653018216SPaolo Bonzini if (initrd_size < 0) {
2476f76b817SAlistair Francis error_report("could not load ram disk '%s' at %x",
24853018216SPaolo Bonzini initrd_filename, RAMDISK_ADDR);
24953018216SPaolo Bonzini exit(1);
25053018216SPaolo Bonzini }
25153018216SPaolo Bonzini }
25253018216SPaolo Bonzini
25353018216SPaolo Bonzini /* If we're loading a kernel directly, we must load the device tree too. */
25453018216SPaolo Bonzini if (kernel_filename) {
2558d42c851SDaniel Henrique Barboza if (bamboo_load_device_tree(machine, FDT_ADDR,
2568d42c851SDaniel Henrique Barboza RAMDISK_ADDR, initrd_size) < 0) {
2576f76b817SAlistair Francis error_report("couldn't load device tree");
25853018216SPaolo Bonzini exit(1);
25953018216SPaolo Bonzini }
26053018216SPaolo Bonzini }
26153018216SPaolo Bonzini }
26253018216SPaolo Bonzini
bamboo_machine_init(MachineClass * mc)263e264d29dSEduardo Habkost static void bamboo_machine_init(MachineClass *mc)
26453018216SPaolo Bonzini {
265e264d29dSEduardo Habkost mc->desc = "bamboo";
266e264d29dSEduardo Habkost mc->init = bamboo_init;
267376d7a2aSIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440epb");
268b28f0188SIgor Mammedov mc->default_ram_id = "ppc4xx.sdram";
269053b7086SThomas Huth mc->default_nic = "e1000";
27053018216SPaolo Bonzini }
27153018216SPaolo Bonzini
272e264d29dSEduardo Habkost DEFINE_MACHINE("bamboo", bamboo_machine_init)
273