xref: /openbmc/qemu/hw/ppc/ppc440_bamboo.c (revision 6b829602e2f10f301ff8508f3a6850a0e913142c)
1  /*
2   * QEMU PowerPC 440 Bamboo board emulation
3   *
4   * Copyright 2007 IBM Corporation.
5   * Authors:
6   *  Jerone Young <jyoung5@us.ibm.com>
7   *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
8   *  Hollis Blanchard <hollisb@us.ibm.com>
9   *
10   * This work is licensed under the GNU GPL license version 2 or later.
11   *
12   */
13  
14  #include "qemu/osdep.h"
15  #include "qemu/units.h"
16  #include "qemu/datadir.h"
17  #include "qemu/error-report.h"
18  #include "exec/page-protection.h"
19  #include "net/net.h"
20  #include "hw/pci/pci.h"
21  #include "hw/boards.h"
22  #include "sysemu/kvm.h"
23  #include "sysemu/device_tree.h"
24  #include "hw/loader.h"
25  #include "elf.h"
26  #include "hw/char/serial-mm.h"
27  #include "hw/ppc/ppc.h"
28  #include "hw/pci-host/ppc4xx.h"
29  #include "sysemu/sysemu.h"
30  #include "sysemu/reset.h"
31  #include "hw/sysbus.h"
32  #include "hw/intc/ppc-uic.h"
33  #include "hw/qdev-properties.h"
34  #include "qapi/error.h"
35  
36  #include <libfdt.h>
37  
38  #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
39  
40  /* from u-boot */
41  #define KERNEL_ADDR  0x1000000
42  #define FDT_ADDR     0x1800000
43  #define RAMDISK_ADDR 0x1900000
44  
45  #define PPC440EP_PCI_CONFIG     0xeec00000
46  #define PPC440EP_PCI_INTACK     0xeed00000
47  #define PPC440EP_PCI_SPECIAL    0xeed00000
48  #define PPC440EP_PCI_REGS       0xef400000
49  #define PPC440EP_PCI_IO         0xe8000000
50  #define PPC440EP_PCI_IOLEN      0x00010000
51  
52  static hwaddr entry;
53  
bamboo_load_device_tree(MachineState * machine,hwaddr addr,hwaddr initrd_base,hwaddr initrd_size)54  static int bamboo_load_device_tree(MachineState *machine,
55                                     hwaddr addr,
56                                     hwaddr initrd_base,
57                                     hwaddr initrd_size)
58  {
59      int ret = -1;
60      uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
61      char *filename;
62      int fdt_size;
63      void *fdt;
64      uint32_t tb_freq = 400000000;
65      uint32_t clock_freq = 400000000;
66  
67      filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
68      if (!filename) {
69          return -1;
70      }
71      fdt = load_device_tree(filename, &fdt_size);
72      g_free(filename);
73      if (fdt == NULL) {
74          return -1;
75      }
76  
77      /* Manipulate device tree in memory. */
78  
79      ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
80                             sizeof(mem_reg_property));
81      if (ret < 0) {
82          fprintf(stderr, "couldn't set /memory/reg\n");
83      }
84      ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
85                                  initrd_base);
86      if (ret < 0) {
87          fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
88      }
89      ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
90                                  (initrd_base + initrd_size));
91      if (ret < 0) {
92          fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
93      }
94      ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
95                                    machine->kernel_cmdline);
96      if (ret < 0) {
97          fprintf(stderr, "couldn't set /chosen/bootargs\n");
98      }
99  
100      qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
101                            clock_freq);
102      qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
103                            tb_freq);
104  
105      rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
106  
107      /* Set ms->fdt for 'dumpdtb' QMP/HMP command */
108      machine->fdt = fdt;
109  
110      return 0;
111  }
112  
main_cpu_reset(void * opaque)113  static void main_cpu_reset(void *opaque)
114  {
115      PowerPCCPU *cpu = opaque;
116      CPUPPCState *env = &cpu->env;
117  
118      cpu_reset(CPU(cpu));
119      env->gpr[1] = (16 * MiB) - 8;
120      env->gpr[3] = FDT_ADDR;
121      env->nip = entry;
122  
123      /* Create a mapping spanning the 32bit addr space. */
124      booke_set_tlb(&env->tlb.tlbe[0], 0, 0, 1U << 31);
125      booke_set_tlb(&env->tlb.tlbe[1], 0x80000000, 0x80000000, 1U << 31);
126  }
127  
bamboo_init(MachineState * machine)128  static void bamboo_init(MachineState *machine)
129  {
130      const char *kernel_filename = machine->kernel_filename;
131      const char *initrd_filename = machine->initrd_filename;
132      MachineClass *mc = MACHINE_GET_CLASS(machine);
133      unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
134      MemoryRegion *address_space_mem = get_system_memory();
135      MemoryRegion *isa = g_new(MemoryRegion, 1);
136      PCIBus *pcibus;
137      PowerPCCPU *cpu;
138      CPUPPCState *env;
139      target_long initrd_size = 0;
140      DeviceState *dev;
141      DeviceState *uicdev;
142      SysBusDevice *uicsbd;
143      int success;
144  
145      if (kvm_enabled()) {
146          error_report("machine %s does not support the KVM accelerator",
147                       MACHINE_GET_CLASS(machine)->name);
148          exit(EXIT_FAILURE);
149      }
150  
151      cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
152      env = &cpu->env;
153  
154      if (env->mmu_model != POWERPC_MMU_BOOKE) {
155          error_report("MMU model %i not supported by this machine",
156                       env->mmu_model);
157          exit(1);
158      }
159  
160      qemu_register_reset(main_cpu_reset, cpu);
161      ppc_booke_timers_init(cpu, 400000000, 0);
162      ppc_dcr_init(env, NULL, NULL);
163  
164      /* interrupt controller */
165      uicdev = qdev_new(TYPE_PPC_UIC);
166      ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal);
167      object_unref(OBJECT(uicdev));
168      uicsbd = SYS_BUS_DEVICE(uicdev);
169      sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT,
170                         qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT));
171      sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT,
172                         qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
173  
174      /* SDRAM controller */
175      dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
176      object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
177                               &error_abort);
178      ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
179      object_unref(OBJECT(dev));
180      /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
181      sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
182      /* Enable SDRAM memory regions, this should be done by the firmware */
183      ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
184  
185      /* PCI */
186      dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST, PPC440EP_PCI_CONFIG,
187                                  qdev_get_gpio_in(uicdev, pci_irq_nrs[0]),
188                                  qdev_get_gpio_in(uicdev, pci_irq_nrs[1]),
189                                  qdev_get_gpio_in(uicdev, pci_irq_nrs[2]),
190                                  qdev_get_gpio_in(uicdev, pci_irq_nrs[3]),
191                                  NULL);
192      pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
193      if (!pcibus) {
194          error_report("couldn't create PCI controller");
195          exit(1);
196      }
197  
198      memory_region_init_alias(isa, NULL, "isa_mmio",
199                               get_system_io(), 0, PPC440EP_PCI_IOLEN);
200      memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa);
201  
202      if (serial_hd(0) != NULL) {
203          serial_mm_init(address_space_mem, 0xef600300, 0,
204                         qdev_get_gpio_in(uicdev, 0),
205                         PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
206                         DEVICE_BIG_ENDIAN);
207      }
208      if (serial_hd(1) != NULL) {
209          serial_mm_init(address_space_mem, 0xef600400, 0,
210                         qdev_get_gpio_in(uicdev, 1),
211                         PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
212                         DEVICE_BIG_ENDIAN);
213      }
214  
215      if (pcibus) {
216          /*
217           * There are no PCI NICs on the Bamboo board, but there are
218           * PCI slots, so we can pick whatever default model we want.
219           */
220          pci_init_nic_devices(pcibus, mc->default_nic);
221      }
222  
223      /* Load kernel. */
224      if (kernel_filename) {
225          hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
226          success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
227                                NULL, NULL);
228          if (success < 0) {
229              uint64_t elf_entry;
230              success = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
231                                 NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
232              entry = elf_entry;
233          }
234          /* XXX try again as binary */
235          if (success < 0) {
236              error_report("could not load kernel '%s'", kernel_filename);
237              exit(1);
238          }
239      }
240  
241      /* Load initrd. */
242      if (initrd_filename) {
243          initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
244                                            machine->ram_size - RAMDISK_ADDR);
245  
246          if (initrd_size < 0) {
247              error_report("could not load ram disk '%s' at %x",
248                           initrd_filename, RAMDISK_ADDR);
249              exit(1);
250          }
251      }
252  
253      /* If we're loading a kernel directly, we must load the device tree too. */
254      if (kernel_filename) {
255          if (bamboo_load_device_tree(machine, FDT_ADDR,
256                                      RAMDISK_ADDR, initrd_size) < 0) {
257              error_report("couldn't load device tree");
258              exit(1);
259          }
260      }
261  }
262  
bamboo_machine_init(MachineClass * mc)263  static void bamboo_machine_init(MachineClass *mc)
264  {
265      mc->desc = "bamboo";
266      mc->init = bamboo_init;
267      mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("440epb");
268      mc->default_ram_id = "ppc4xx.sdram";
269      mc->default_nic = "e1000";
270  }
271  
272  DEFINE_MACHINE("bamboo", bamboo_machine_init)
273