]> git.proxmox.com Git - qemu.git/blob - hw/ppc440_bamboo.c
PPC: Bamboo: fold ppc440.c and ppc440_bamboo.c into a single file
[qemu.git] / hw / ppc440_bamboo.c
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 "config.h"
15 #include "qemu-common.h"
16 #include "net.h"
17 #include "hw.h"
18 #include "pci.h"
19 #include "boards.h"
20 #include "kvm.h"
21 #include "kvm_ppc.h"
22 #include "device_tree.h"
23 #include "loader.h"
24 #include "elf.h"
25 #include "exec-memory.h"
26 #include "pc.h"
27 #include "ppc.h"
28 #include "ppc405.h"
29 #include "sysemu.h"
30
31 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
32
33 /* from u-boot */
34 #define KERNEL_ADDR 0x1000000
35 #define FDT_ADDR 0x1800000
36 #define RAMDISK_ADDR 0x1900000
37
38 #define PPC440EP_PCI_CONFIG 0xeec00000
39 #define PPC440EP_PCI_INTACK 0xeed00000
40 #define PPC440EP_PCI_SPECIAL 0xeed00000
41 #define PPC440EP_PCI_REGS 0xef400000
42 #define PPC440EP_PCI_IO 0xe8000000
43 #define PPC440EP_PCI_IOLEN 0x00010000
44
45 #define PPC440EP_SDRAM_NR_BANKS 4
46
47 static const unsigned int ppc440ep_sdram_bank_sizes[] = {
48 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
49 };
50
51 static target_phys_addr_t entry;
52
53 static PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
54 target_phys_addr_t config_space,
55 target_phys_addr_t int_ack,
56 target_phys_addr_t special_cycle,
57 target_phys_addr_t registers)
58 {
59 return NULL;
60 }
61
62 CPUState *ppc440ep_init(MemoryRegion *address_space_mem, ram_addr_t *ram_size,
63 PCIBus **pcip, const unsigned int pci_irq_nrs[4],
64 int do_init, const char *cpu_model)
65 {
66 MemoryRegion *ram_memories
67 = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
68 target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS];
69 target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS];
70 CPUState *env;
71 qemu_irq *pic;
72 qemu_irq *irqs;
73 qemu_irq *pci_irqs;
74
75 if (cpu_model == NULL) {
76 cpu_model = "440EP";
77 }
78 env = cpu_init(cpu_model);
79 if (!env) {
80 fprintf(stderr, "Unable to initialize CPU!\n");
81 exit(1);
82 }
83
84 ppc_booke_timers_init(env, 400000000, 0);
85 ppc_dcr_init(env, NULL, NULL);
86
87 /* interrupt controller */
88 irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
89 irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
90 irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
91 pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
92
93 /* SDRAM controller */
94 memset(ram_bases, 0, sizeof(ram_bases));
95 memset(ram_sizes, 0, sizeof(ram_sizes));
96 *ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS,
97 ram_memories,
98 ram_bases, ram_sizes,
99 ppc440ep_sdram_bank_sizes);
100 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
101 ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
102 ram_bases, ram_sizes, do_init);
103
104 /* PCI */
105 pci_irqs = g_malloc(sizeof(qemu_irq) * 4);
106 pci_irqs[0] = pic[pci_irq_nrs[0]];
107 pci_irqs[1] = pic[pci_irq_nrs[1]];
108 pci_irqs[2] = pic[pci_irq_nrs[2]];
109 pci_irqs[3] = pic[pci_irq_nrs[3]];
110 *pcip = ppc4xx_pci_init(env, pci_irqs,
111 PPC440EP_PCI_CONFIG,
112 PPC440EP_PCI_INTACK,
113 PPC440EP_PCI_SPECIAL,
114 PPC440EP_PCI_REGS);
115 if (!*pcip)
116 printf("couldn't create PCI controller!\n");
117
118 isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
119
120 if (serial_hds[0] != NULL) {
121 serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
122 PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
123 DEVICE_BIG_ENDIAN);
124 }
125 if (serial_hds[1] != NULL) {
126 serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
127 PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
128 DEVICE_BIG_ENDIAN);
129 }
130
131 return env;
132 }
133
134 static int bamboo_load_device_tree(target_phys_addr_t addr,
135 uint32_t ramsize,
136 target_phys_addr_t initrd_base,
137 target_phys_addr_t initrd_size,
138 const char *kernel_cmdline)
139 {
140 int ret = -1;
141 #ifdef CONFIG_FDT
142 uint32_t mem_reg_property[] = { 0, 0, ramsize };
143 char *filename;
144 int fdt_size;
145 void *fdt;
146 uint32_t tb_freq = 400000000;
147 uint32_t clock_freq = 400000000;
148
149 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
150 if (!filename) {
151 goto out;
152 }
153 fdt = load_device_tree(filename, &fdt_size);
154 g_free(filename);
155 if (fdt == NULL) {
156 goto out;
157 }
158
159 /* Manipulate device tree in memory. */
160
161 ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
162 sizeof(mem_reg_property));
163 if (ret < 0)
164 fprintf(stderr, "couldn't set /memory/reg\n");
165
166 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
167 initrd_base);
168 if (ret < 0)
169 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
170
171 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
172 (initrd_base + initrd_size));
173 if (ret < 0)
174 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
175
176 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
177 kernel_cmdline);
178 if (ret < 0)
179 fprintf(stderr, "couldn't set /chosen/bootargs\n");
180
181 /* Copy data from the host device tree into the guest. Since the guest can
182 * directly access the timebase without host involvement, we must expose
183 * the correct frequencies. */
184 if (kvm_enabled()) {
185 tb_freq = kvmppc_get_tbfreq();
186 clock_freq = kvmppc_get_clockfreq();
187 }
188
189 qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
190 clock_freq);
191 qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
192 tb_freq);
193
194 ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
195 g_free(fdt);
196
197 out:
198 #endif
199
200 return ret;
201 }
202
203 /* Create reset TLB entries for BookE, spanning the 32bit addr space. */
204 static void mmubooke_create_initial_mapping(CPUState *env,
205 target_ulong va,
206 target_phys_addr_t pa)
207 {
208 ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
209
210 tlb->attr = 0;
211 tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
212 tlb->size = 1 << 31; /* up to 0x80000000 */
213 tlb->EPN = va & TARGET_PAGE_MASK;
214 tlb->RPN = pa & TARGET_PAGE_MASK;
215 tlb->PID = 0;
216
217 tlb = &env->tlb.tlbe[1];
218 tlb->attr = 0;
219 tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
220 tlb->size = 1 << 31; /* up to 0xffffffff */
221 tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
222 tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
223 tlb->PID = 0;
224 }
225
226 static void main_cpu_reset(void *opaque)
227 {
228 CPUState *env = opaque;
229
230 cpu_reset(env);
231 env->gpr[1] = (16<<20) - 8;
232 env->gpr[3] = FDT_ADDR;
233 env->nip = entry;
234
235 /* Create a mapping for the kernel. */
236 mmubooke_create_initial_mapping(env, 0, 0);
237 }
238
239 static void bamboo_init(ram_addr_t ram_size,
240 const char *boot_device,
241 const char *kernel_filename,
242 const char *kernel_cmdline,
243 const char *initrd_filename,
244 const char *cpu_model)
245 {
246 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
247 MemoryRegion *address_space_mem = get_system_memory();
248 PCIBus *pcibus;
249 CPUState *env;
250 uint64_t elf_entry;
251 uint64_t elf_lowaddr;
252 target_phys_addr_t loadaddr = 0;
253 target_long initrd_size = 0;
254 int success;
255 int i;
256
257 /* Setup CPU. */
258 env = ppc440ep_init(address_space_mem, &ram_size, &pcibus,
259 pci_irq_nrs, 1, cpu_model);
260 qemu_register_reset(main_cpu_reset, env);
261
262 if (pcibus) {
263 /* Register network interfaces. */
264 for (i = 0; i < nb_nics; i++) {
265 /* There are no PCI NICs on the Bamboo board, but there are
266 * PCI slots, so we can pick whatever default model we want. */
267 pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
268 }
269 }
270
271 /* Load kernel. */
272 if (kernel_filename) {
273 success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
274 if (success < 0) {
275 success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
276 &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
277 entry = elf_entry;
278 loadaddr = elf_lowaddr;
279 }
280 /* XXX try again as binary */
281 if (success < 0) {
282 fprintf(stderr, "qemu: could not load kernel '%s'\n",
283 kernel_filename);
284 exit(1);
285 }
286 }
287
288 /* Load initrd. */
289 if (initrd_filename) {
290 initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
291 ram_size - RAMDISK_ADDR);
292
293 if (initrd_size < 0) {
294 fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
295 initrd_filename, RAMDISK_ADDR);
296 exit(1);
297 }
298 }
299
300 /* If we're loading a kernel directly, we must load the device tree too. */
301 if (kernel_filename) {
302 if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
303 initrd_size, kernel_cmdline) < 0) {
304 fprintf(stderr, "couldn't load device tree\n");
305 exit(1);
306 }
307 }
308
309 if (kvm_enabled())
310 kvmppc_init();
311 }
312
313 static QEMUMachine bamboo_machine = {
314 .name = "bamboo",
315 .desc = "bamboo",
316 .init = bamboo_init,
317 };
318
319 static void bamboo_machine_init(void)
320 {
321 qemu_register_machine(&bamboo_machine);
322 }
323
324 machine_init(bamboo_machine_init);