|
1 /* |
|
2 * Qemu PowerPC 440 chip 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 "hw.h" |
|
15 #include "isa.h" |
|
16 #include "ppc.h" |
|
17 #include "ppc4xx.h" |
|
18 #include "ppc440.h" |
|
19 #include "ppc405.h" |
|
20 #include "sysemu.h" |
|
21 #include "kvm.h" |
|
22 |
|
23 #define PPC440EP_PCI_CONFIG 0xeec00000 |
|
24 #define PPC440EP_PCI_INTACK 0xeed00000 |
|
25 #define PPC440EP_PCI_SPECIAL 0xeed00000 |
|
26 #define PPC440EP_PCI_REGS 0xef400000 |
|
27 #define PPC440EP_PCI_IO 0xe8000000 |
|
28 #define PPC440EP_PCI_IOLEN 0x00010000 |
|
29 |
|
30 #define PPC440EP_SDRAM_NR_BANKS 4 |
|
31 |
|
32 static const unsigned int ppc440ep_sdram_bank_sizes[] = { |
|
33 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0 |
|
34 }; |
|
35 |
|
36 CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip, |
|
37 const unsigned int pci_irq_nrs[4], int do_init) |
|
38 { |
|
39 target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS]; |
|
40 target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS]; |
|
41 CPUState *env; |
|
42 ppc4xx_mmio_t *mmio; |
|
43 qemu_irq *pic; |
|
44 qemu_irq *irqs; |
|
45 qemu_irq *pci_irqs; |
|
46 |
|
47 env = cpu_ppc_init("440EP"); |
|
48 if (!env && kvm_enabled()) { |
|
49 /* XXX Since qemu doesn't yet emulate 440, we just say it's a 405. |
|
50 * Since KVM doesn't use qemu's CPU emulation it seems to be working |
|
51 * OK. */ |
|
52 env = cpu_ppc_init("405"); |
|
53 } |
|
54 if (!env) { |
|
55 fprintf(stderr, "Unable to initialize CPU!\n"); |
|
56 exit(1); |
|
57 } |
|
58 |
|
59 ppc_dcr_init(env, NULL, NULL); |
|
60 |
|
61 /* interrupt controller */ |
|
62 irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); |
|
63 irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; |
|
64 irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; |
|
65 pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); |
|
66 |
|
67 /* SDRAM controller */ |
|
68 memset(ram_bases, 0, sizeof(ram_bases)); |
|
69 memset(ram_sizes, 0, sizeof(ram_sizes)); |
|
70 *ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS, |
|
71 ram_bases, ram_sizes, |
|
72 ppc440ep_sdram_bank_sizes); |
|
73 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */ |
|
74 ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_bases, |
|
75 ram_sizes, do_init); |
|
76 |
|
77 /* PCI */ |
|
78 pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4); |
|
79 pci_irqs[0] = pic[pci_irq_nrs[0]]; |
|
80 pci_irqs[1] = pic[pci_irq_nrs[1]]; |
|
81 pci_irqs[2] = pic[pci_irq_nrs[2]]; |
|
82 pci_irqs[3] = pic[pci_irq_nrs[3]]; |
|
83 *pcip = ppc4xx_pci_init(env, pci_irqs, |
|
84 PPC440EP_PCI_CONFIG, |
|
85 PPC440EP_PCI_INTACK, |
|
86 PPC440EP_PCI_SPECIAL, |
|
87 PPC440EP_PCI_REGS); |
|
88 if (!*pcip) |
|
89 printf("couldn't create PCI controller!\n"); |
|
90 |
|
91 isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN); |
|
92 |
|
93 /* MMIO -- most "miscellaneous" devices live above 0xef600000. */ |
|
94 mmio = ppc4xx_mmio_init(env, 0xef600000); |
|
95 |
|
96 if (serial_hds[0]) |
|
97 ppc405_serial_init(env, mmio, 0x300, pic[0], serial_hds[0]); |
|
98 |
|
99 if (serial_hds[1]) |
|
100 ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]); |
|
101 |
|
102 return env; |
|
103 } |