Statistics
| Branch: | Revision:

root / hw / ppc440_bamboo.c @ 771124e1

History | View | Annotate | Download (9.3 kB)

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