ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 1 | /* |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 2 | * ARM Versatile Platform/Application Baseboard System emulation. |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 3 | * |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 4 | * Copyright (c) 2005-2007 CodeSourcery. |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 5 | * Written by Paul Brook |
| 6 | * |
Matthew Fernandez | 8e31bf3 | 2011-06-26 12:21:35 +1000 | [diff] [blame] | 7 | * This code is licensed under the GPL. |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
Paul Brook | 2e9bdce | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 10 | #include "sysbus.h" |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 11 | #include "arm-misc.h" |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 12 | #include "devices.h" |
| 13 | #include "net.h" |
| 14 | #include "sysemu.h" |
| 15 | #include "pci.h" |
Oskar Andero | b1f0569 | 2012-04-20 15:38:52 +0000 | [diff] [blame] | 16 | #include "i2c.h" |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 17 | #include "boards.h" |
Blue Swirl | 2446333 | 2010-08-24 15:22:24 +0000 | [diff] [blame] | 18 | #include "blockdev.h" |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 19 | #include "exec-memory.h" |
Eric Benard | 964c695 | 2012-04-16 05:02:47 +0000 | [diff] [blame] | 20 | #include "flash.h" |
| 21 | |
| 22 | #define VERSATILE_FLASH_ADDR 0x34000000 |
| 23 | #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024) |
| 24 | #define VERSATILE_FLASH_SECT_SIZE (256 * 1024) |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 25 | |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 26 | /* Primary interrupt controller. */ |
| 27 | |
| 28 | typedef struct vpb_sic_state |
| 29 | { |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 30 | SysBusDevice busdev; |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 31 | MemoryRegion iomem; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 32 | uint32_t level; |
| 33 | uint32_t mask; |
| 34 | uint32_t pic_enable; |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 35 | qemu_irq parent[32]; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 36 | int irq; |
| 37 | } vpb_sic_state; |
| 38 | |
Peter Maydell | a796d0a | 2010-12-23 17:19:52 +0000 | [diff] [blame] | 39 | static const VMStateDescription vmstate_vpb_sic = { |
| 40 | .name = "versatilepb_sic", |
| 41 | .version_id = 1, |
| 42 | .minimum_version_id = 1, |
| 43 | .fields = (VMStateField[]) { |
| 44 | VMSTATE_UINT32(level, vpb_sic_state), |
| 45 | VMSTATE_UINT32(mask, vpb_sic_state), |
| 46 | VMSTATE_UINT32(pic_enable, vpb_sic_state), |
| 47 | VMSTATE_END_OF_LIST() |
| 48 | } |
| 49 | }; |
| 50 | |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 51 | static void vpb_sic_update(vpb_sic_state *s) |
| 52 | { |
| 53 | uint32_t flags; |
| 54 | |
| 55 | flags = s->level & s->mask; |
pbrook | d537cf6 | 2007-04-07 18:14:41 +0000 | [diff] [blame] | 56 | qemu_set_irq(s->parent[s->irq], flags != 0); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | static void vpb_sic_update_pic(vpb_sic_state *s) |
| 60 | { |
| 61 | int i; |
| 62 | uint32_t mask; |
| 63 | |
| 64 | for (i = 21; i <= 30; i++) { |
| 65 | mask = 1u << i; |
| 66 | if (!(s->pic_enable & mask)) |
| 67 | continue; |
pbrook | d537cf6 | 2007-04-07 18:14:41 +0000 | [diff] [blame] | 68 | qemu_set_irq(s->parent[i], (s->level & mask) != 0); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 69 | } |
| 70 | } |
| 71 | |
| 72 | static void vpb_sic_set_irq(void *opaque, int irq, int level) |
| 73 | { |
| 74 | vpb_sic_state *s = (vpb_sic_state *)opaque; |
| 75 | if (level) |
| 76 | s->level |= 1u << irq; |
| 77 | else |
| 78 | s->level &= ~(1u << irq); |
| 79 | if (s->pic_enable & (1u << irq)) |
pbrook | d537cf6 | 2007-04-07 18:14:41 +0000 | [diff] [blame] | 80 | qemu_set_irq(s->parent[irq], level); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 81 | vpb_sic_update(s); |
| 82 | } |
| 83 | |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 84 | static uint64_t vpb_sic_read(void *opaque, target_phys_addr_t offset, |
| 85 | unsigned size) |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 86 | { |
| 87 | vpb_sic_state *s = (vpb_sic_state *)opaque; |
| 88 | |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 89 | switch (offset >> 2) { |
| 90 | case 0: /* STATUS */ |
| 91 | return s->level & s->mask; |
| 92 | case 1: /* RAWSTAT */ |
| 93 | return s->level; |
| 94 | case 2: /* ENABLE */ |
| 95 | return s->mask; |
| 96 | case 4: /* SOFTINT */ |
| 97 | return s->level & 1; |
| 98 | case 8: /* PICENABLE */ |
| 99 | return s->pic_enable; |
| 100 | default: |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 101 | printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 102 | return 0; |
| 103 | } |
| 104 | } |
| 105 | |
Anthony Liguori | c227f09 | 2009-10-01 16:12:16 -0500 | [diff] [blame] | 106 | static void vpb_sic_write(void *opaque, target_phys_addr_t offset, |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 107 | uint64_t value, unsigned size) |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 108 | { |
| 109 | vpb_sic_state *s = (vpb_sic_state *)opaque; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 110 | |
| 111 | switch (offset >> 2) { |
| 112 | case 2: /* ENSET */ |
| 113 | s->mask |= value; |
| 114 | break; |
| 115 | case 3: /* ENCLR */ |
| 116 | s->mask &= ~value; |
| 117 | break; |
| 118 | case 4: /* SOFTINTSET */ |
| 119 | if (value) |
| 120 | s->mask |= 1; |
| 121 | break; |
| 122 | case 5: /* SOFTINTCLR */ |
| 123 | if (value) |
| 124 | s->mask &= ~1u; |
| 125 | break; |
| 126 | case 8: /* PICENSET */ |
| 127 | s->pic_enable |= (value & 0x7fe00000); |
| 128 | vpb_sic_update_pic(s); |
| 129 | break; |
| 130 | case 9: /* PICENCLR */ |
| 131 | s->pic_enable &= ~value; |
| 132 | vpb_sic_update_pic(s); |
| 133 | break; |
| 134 | default: |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 135 | printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 136 | return; |
| 137 | } |
| 138 | vpb_sic_update(s); |
| 139 | } |
| 140 | |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 141 | static const MemoryRegionOps vpb_sic_ops = { |
| 142 | .read = vpb_sic_read, |
| 143 | .write = vpb_sic_write, |
| 144 | .endianness = DEVICE_NATIVE_ENDIAN, |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 145 | }; |
| 146 | |
Gerd Hoffmann | 81a322d | 2009-08-14 10:36:05 +0200 | [diff] [blame] | 147 | static int vpb_sic_init(SysBusDevice *dev) |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 148 | { |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 149 | vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 150 | int i; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 151 | |
Paul Brook | 067a3dd | 2009-05-26 14:56:11 +0100 | [diff] [blame] | 152 | qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 153 | for (i = 0; i < 32; i++) { |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 154 | sysbus_init_irq(dev, &s->parent[i]); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 155 | } |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 156 | s->irq = 31; |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 157 | memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000); |
Avi Kivity | 750ecd4 | 2011-11-27 11:38:10 +0200 | [diff] [blame] | 158 | sysbus_init_mmio(dev, &s->iomem); |
Gerd Hoffmann | 81a322d | 2009-08-14 10:36:05 +0200 | [diff] [blame] | 159 | return 0; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | /* Board init. */ |
| 163 | |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 164 | /* The AB and PB boards both use the same core, just with different |
Stefan Weil | 370de02 | 2012-08-10 21:56:46 +0200 | [diff] [blame] | 165 | peripherals and expansion busses. For now we emulate a subset of the |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 166 | PB peripherals and just change the board ID. */ |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 167 | |
balrog | f93eb9f | 2008-04-14 20:27:51 +0000 | [diff] [blame] | 168 | static struct arm_boot_info versatile_binfo; |
| 169 | |
Anthony Liguori | c227f09 | 2009-10-01 16:12:16 -0500 | [diff] [blame] | 170 | static void versatile_init(ram_addr_t ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 171 | const char *boot_device, |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 172 | const char *kernel_filename, const char *kernel_cmdline, |
pbrook | 3371d27 | 2007-03-08 03:04:12 +0000 | [diff] [blame] | 173 | const char *initrd_filename, const char *cpu_model, |
| 174 | int board_id) |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 175 | { |
Andreas Färber | 20e9337 | 2012-05-14 02:04:38 +0200 | [diff] [blame] | 176 | ARMCPU *cpu; |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 177 | MemoryRegion *sysmem = get_system_memory(); |
| 178 | MemoryRegion *ram = g_new(MemoryRegion, 1); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 179 | qemu_irq *cpu_pic; |
| 180 | qemu_irq pic[32]; |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 181 | qemu_irq sic[32]; |
Peter Maydell | 242ea2c | 2011-07-22 13:42:39 +0000 | [diff] [blame] | 182 | DeviceState *dev, *sysctl; |
Peter Maydell | 7d6e771 | 2011-09-01 18:36:53 +0100 | [diff] [blame] | 183 | SysBusDevice *busdev; |
Mathieu Sonet | d028d02 | 2011-10-28 10:55:37 +0100 | [diff] [blame] | 184 | DeviceState *pl041; |
pbrook | 502a539 | 2006-05-13 16:11:23 +0000 | [diff] [blame] | 185 | PCIBus *pci_bus; |
| 186 | NICInfo *nd; |
Oskar Andero | b1f0569 | 2012-04-20 15:38:52 +0000 | [diff] [blame] | 187 | i2c_bus *i2c; |
pbrook | 502a539 | 2006-05-13 16:11:23 +0000 | [diff] [blame] | 188 | int n; |
| 189 | int done_smc = 0; |
Eric Benard | 964c695 | 2012-04-16 05:02:47 +0000 | [diff] [blame] | 190 | DriveInfo *dinfo; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 191 | |
Andreas Färber | 20e9337 | 2012-05-14 02:04:38 +0200 | [diff] [blame] | 192 | if (!cpu_model) { |
pbrook | 3371d27 | 2007-03-08 03:04:12 +0000 | [diff] [blame] | 193 | cpu_model = "arm926"; |
Andreas Färber | 20e9337 | 2012-05-14 02:04:38 +0200 | [diff] [blame] | 194 | } |
| 195 | cpu = cpu_arm_init(cpu_model); |
| 196 | if (!cpu) { |
bellard | aaed909 | 2007-11-10 15:15:54 +0000 | [diff] [blame] | 197 | fprintf(stderr, "Unable to find CPU definition\n"); |
| 198 | exit(1); |
| 199 | } |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 200 | memory_region_init_ram(ram, "versatile.ram", ram_size); |
| 201 | vmstate_register_ram_global(ram); |
ths | 1235fc0 | 2008-06-03 19:51:57 +0000 | [diff] [blame] | 202 | /* ??? RAM should repeat to fill physical memory space. */ |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 203 | /* SDRAM at address zero. */ |
Avi Kivity | 62ceeb2 | 2011-10-05 18:41:32 +0200 | [diff] [blame] | 204 | memory_region_add_subregion(sysmem, 0, ram); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 205 | |
Peter Maydell | 242ea2c | 2011-07-22 13:42:39 +0000 | [diff] [blame] | 206 | sysctl = qdev_create(NULL, "realview_sysctl"); |
| 207 | qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004); |
Peter Maydell | 242ea2c | 2011-07-22 13:42:39 +0000 | [diff] [blame] | 208 | qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000); |
Peter Maydell | 7a65c8c | 2012-02-09 06:11:16 +0000 | [diff] [blame] | 209 | qdev_init_nofail(sysctl); |
Peter Maydell | 242ea2c | 2011-07-22 13:42:39 +0000 | [diff] [blame] | 210 | sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000); |
| 211 | |
Andreas Färber | 4bd7466 | 2012-05-14 04:21:52 +0200 | [diff] [blame] | 212 | cpu_pic = arm_pic_init_cpu(cpu); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 213 | dev = sysbus_create_varargs("pl190", 0x10140000, |
Stefan Weil | 02cd521 | 2012-10-04 22:49:43 +0200 | [diff] [blame] | 214 | cpu_pic[ARM_PIC_CPU_IRQ], |
| 215 | cpu_pic[ARM_PIC_CPU_FIQ], NULL); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 216 | for (n = 0; n < 32; n++) { |
Paul Brook | 067a3dd | 2009-05-26 14:56:11 +0100 | [diff] [blame] | 217 | pic[n] = qdev_get_gpio_in(dev, n); |
Paul Brook | 97aff48 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 218 | } |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 219 | dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL); |
| 220 | for (n = 0; n < 32; n++) { |
| 221 | sysbus_connect_irq(sysbus_from_qdev(dev), n, pic[n]); |
Paul Brook | 067a3dd | 2009-05-26 14:56:11 +0100 | [diff] [blame] | 222 | sic[n] = qdev_get_gpio_in(dev, n); |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 223 | } |
Paul Brook | 86394e9 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 224 | |
| 225 | sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]); |
| 226 | sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 227 | |
Peter Maydell | 7d6e771 | 2011-09-01 18:36:53 +0100 | [diff] [blame] | 228 | dev = qdev_create(NULL, "versatile_pci"); |
| 229 | busdev = sysbus_from_qdev(dev); |
| 230 | qdev_init_nofail(dev); |
| 231 | sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */ |
| 232 | sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */ |
| 233 | sysbus_connect_irq(busdev, 0, sic[27]); |
| 234 | sysbus_connect_irq(busdev, 1, sic[28]); |
| 235 | sysbus_connect_irq(busdev, 2, sic[29]); |
| 236 | sysbus_connect_irq(busdev, 3, sic[30]); |
Paul Brook | 02e2da4 | 2009-05-23 00:05:19 +0100 | [diff] [blame] | 237 | pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); |
Paul Brook | 0027b06 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 238 | |
pbrook | 502a539 | 2006-05-13 16:11:23 +0000 | [diff] [blame] | 239 | /* The Versatile PCI bridge does not provide access to PCI IO space, |
| 240 | so many of the qemu PCI devices are not useable. */ |
| 241 | for(n = 0; n < nb_nics; n++) { |
| 242 | nd = &nd_table[n]; |
aliguori | 0ae18ce | 2009-01-13 19:39:36 +0000 | [diff] [blame] | 243 | |
Peter Maydell | e6b3c8c | 2011-03-22 18:21:58 +0000 | [diff] [blame] | 244 | if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) { |
pbrook | d537cf6 | 2007-04-07 18:14:41 +0000 | [diff] [blame] | 245 | smc91c111_init(nd, 0x10010000, sic[25]); |
aliguori | 0ae18ce | 2009-01-13 19:39:36 +0000 | [diff] [blame] | 246 | done_smc = 1; |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 247 | } else { |
Markus Armbruster | 07caea3 | 2009-09-25 03:53:51 +0200 | [diff] [blame] | 248 | pci_nic_init_nofail(nd, "rtl8139", NULL); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 249 | } |
| 250 | } |
pbrook | 0d92ed3 | 2006-05-21 16:30:15 +0000 | [diff] [blame] | 251 | if (usb_enabled) { |
Gerd Hoffmann | afb9a60 | 2012-03-07 15:06:32 +0100 | [diff] [blame] | 252 | pci_create_simple(pci_bus, -1, "pci-ohci"); |
pbrook | 0d92ed3 | 2006-05-21 16:30:15 +0000 | [diff] [blame] | 253 | } |
Paul Brook | 9be5daf | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 254 | n = drive_get_max_bus(IF_SCSI); |
| 255 | while (n >= 0) { |
| 256 | pci_create_simple(pci_bus, -1, "lsi53c895a"); |
| 257 | n--; |
pbrook | 7d8406b | 2006-05-30 01:48:12 +0000 | [diff] [blame] | 258 | } |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 259 | |
Paul Brook | a7d518a | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 260 | sysbus_create_simple("pl011", 0x101f1000, pic[12]); |
| 261 | sysbus_create_simple("pl011", 0x101f2000, pic[13]); |
| 262 | sysbus_create_simple("pl011", 0x101f3000, pic[14]); |
| 263 | sysbus_create_simple("pl011", 0x10009000, sic[6]); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 264 | |
Paul Brook | b4496b1 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 265 | sysbus_create_simple("pl080", 0x10130000, pic[17]); |
Paul Brook | 6a824ec | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 266 | sysbus_create_simple("sp804", 0x101e2000, pic[4]); |
| 267 | sysbus_create_simple("sp804", 0x101e3000, pic[5]); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 268 | |
Jean-Christophe PLAGNIOL-VILLARD | 853e65e | 2012-10-12 11:54:39 +0100 | [diff] [blame^] | 269 | sysbus_create_simple("pl061", 0x101e4000, pic[6]); |
| 270 | sysbus_create_simple("pl061", 0x101e5000, pic[7]); |
| 271 | sysbus_create_simple("pl061", 0x101e6000, pic[8]); |
| 272 | sysbus_create_simple("pl061", 0x101e7000, pic[9]); |
| 273 | |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 274 | /* The versatile/PB actually has a modified Color LCD controller |
| 275 | that includes hardware cursor support from the PL111. */ |
Peter Maydell | 242ea2c | 2011-07-22 13:42:39 +0000 | [diff] [blame] | 276 | dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]); |
| 277 | /* Wire up the mux control signals from the SYS_CLCD register */ |
| 278 | qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0)); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 279 | |
Paul Brook | aa9311d | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 280 | sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL); |
| 281 | sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL); |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 282 | |
pbrook | 7e1543c | 2007-06-30 17:32:17 +0000 | [diff] [blame] | 283 | /* Add PL031 Real Time Clock. */ |
Paul Brook | a63bdb3 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 284 | sysbus_create_simple("pl031", 0x101e8000, pic[10]); |
pbrook | 7e1543c | 2007-06-30 17:32:17 +0000 | [diff] [blame] | 285 | |
Oskar Andero | b1f0569 | 2012-04-20 15:38:52 +0000 | [diff] [blame] | 286 | dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); |
| 287 | i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); |
| 288 | i2c_create_slave(i2c, "ds1338", 0x68); |
| 289 | |
Mathieu Sonet | d028d02 | 2011-10-28 10:55:37 +0100 | [diff] [blame] | 290 | /* Add PL041 AACI Interface to the LM4549 codec */ |
| 291 | pl041 = qdev_create(NULL, "pl041"); |
| 292 | qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); |
| 293 | qdev_init_nofail(pl041); |
| 294 | sysbus_mmio_map(sysbus_from_qdev(pl041), 0, 0x10004000); |
| 295 | sysbus_connect_irq(sysbus_from_qdev(pl041), 0, sic[24]); |
| 296 | |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 297 | /* Memory map for Versatile/PB: */ |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 298 | /* 0x10000000 System registers. */ |
| 299 | /* 0x10001000 PCI controller config registers. */ |
| 300 | /* 0x10002000 Serial bus interface. */ |
| 301 | /* 0x10003000 Secondary interrupt controller. */ |
| 302 | /* 0x10004000 AACI (audio). */ |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 303 | /* 0x10005000 MMCI0. */ |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 304 | /* 0x10006000 KMI0 (keyboard). */ |
| 305 | /* 0x10007000 KMI1 (mouse). */ |
| 306 | /* 0x10008000 Character LCD Interface. */ |
| 307 | /* 0x10009000 UART3. */ |
| 308 | /* 0x1000a000 Smart card 1. */ |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 309 | /* 0x1000b000 MMCI1. */ |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 310 | /* 0x10010000 Ethernet. */ |
| 311 | /* 0x10020000 USB. */ |
| 312 | /* 0x10100000 SSMC. */ |
| 313 | /* 0x10110000 MPMC. */ |
| 314 | /* 0x10120000 CLCD Controller. */ |
| 315 | /* 0x10130000 DMA Controller. */ |
| 316 | /* 0x10140000 Vectored interrupt controller. */ |
| 317 | /* 0x101d0000 AHB Monitor Interface. */ |
| 318 | /* 0x101e0000 System Controller. */ |
| 319 | /* 0x101e1000 Watchdog Interface. */ |
| 320 | /* 0x101e2000 Timer 0/1. */ |
| 321 | /* 0x101e3000 Timer 2/3. */ |
| 322 | /* 0x101e4000 GPIO port 0. */ |
| 323 | /* 0x101e5000 GPIO port 1. */ |
| 324 | /* 0x101e6000 GPIO port 2. */ |
| 325 | /* 0x101e7000 GPIO port 3. */ |
| 326 | /* 0x101e8000 RTC. */ |
| 327 | /* 0x101f0000 Smart card 0. */ |
| 328 | /* 0x101f1000 UART0. */ |
| 329 | /* 0x101f2000 UART1. */ |
| 330 | /* 0x101f3000 UART2. */ |
| 331 | /* 0x101f4000 SSPI. */ |
Eric Benard | 964c695 | 2012-04-16 05:02:47 +0000 | [diff] [blame] | 332 | /* 0x34000000 NOR Flash */ |
| 333 | |
| 334 | dinfo = drive_get(IF_PFLASH, 0, 0); |
| 335 | if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash", |
| 336 | VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, |
| 337 | VERSATILE_FLASH_SECT_SIZE, |
| 338 | VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE, |
| 339 | 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) { |
| 340 | fprintf(stderr, "qemu: Error registering flash memory.\n"); |
| 341 | } |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 342 | |
balrog | f93eb9f | 2008-04-14 20:27:51 +0000 | [diff] [blame] | 343 | versatile_binfo.ram_size = ram_size; |
| 344 | versatile_binfo.kernel_filename = kernel_filename; |
| 345 | versatile_binfo.kernel_cmdline = kernel_cmdline; |
| 346 | versatile_binfo.initrd_filename = initrd_filename; |
| 347 | versatile_binfo.board_id = board_id; |
Andreas Färber | 3aaa8df | 2012-05-14 02:39:57 +0200 | [diff] [blame] | 348 | arm_load_kernel(cpu, &versatile_binfo); |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 349 | } |
| 350 | |
Anthony Liguori | c227f09 | 2009-10-01 16:12:16 -0500 | [diff] [blame] | 351 | static void vpb_init(ram_addr_t ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 352 | const char *boot_device, |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 353 | const char *kernel_filename, const char *kernel_cmdline, |
j_mayer | 94fc95c | 2007-03-05 19:44:02 +0000 | [diff] [blame] | 354 | const char *initrd_filename, const char *cpu_model) |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 355 | { |
Paul Brook | fbe1b59 | 2009-05-13 17:56:25 +0100 | [diff] [blame] | 356 | versatile_init(ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 357 | boot_device, |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 358 | kernel_filename, kernel_cmdline, |
pbrook | 3371d27 | 2007-03-08 03:04:12 +0000 | [diff] [blame] | 359 | initrd_filename, cpu_model, 0x183); |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 360 | } |
| 361 | |
Anthony Liguori | c227f09 | 2009-10-01 16:12:16 -0500 | [diff] [blame] | 362 | static void vab_init(ram_addr_t ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 363 | const char *boot_device, |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 364 | const char *kernel_filename, const char *kernel_cmdline, |
j_mayer | 94fc95c | 2007-03-05 19:44:02 +0000 | [diff] [blame] | 365 | const char *initrd_filename, const char *cpu_model) |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 366 | { |
Paul Brook | fbe1b59 | 2009-05-13 17:56:25 +0100 | [diff] [blame] | 367 | versatile_init(ram_size, |
aliguori | 3023f33 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 368 | boot_device, |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 369 | kernel_filename, kernel_cmdline, |
pbrook | 3371d27 | 2007-03-08 03:04:12 +0000 | [diff] [blame] | 370 | initrd_filename, cpu_model, 0x25e); |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 371 | } |
| 372 | |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 373 | static QEMUMachine versatilepb_machine = { |
blueswir1 | c9b1ae2 | 2008-09-28 18:55:17 +0000 | [diff] [blame] | 374 | .name = "versatilepb", |
| 375 | .desc = "ARM Versatile/PB (ARM926EJ-S)", |
| 376 | .init = vpb_init, |
| 377 | .use_scsi = 1, |
pbrook | cdbdb64 | 2006-04-09 01:32:52 +0000 | [diff] [blame] | 378 | }; |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 379 | |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 380 | static QEMUMachine versatileab_machine = { |
blueswir1 | c9b1ae2 | 2008-09-28 18:55:17 +0000 | [diff] [blame] | 381 | .name = "versatileab", |
| 382 | .desc = "ARM Versatile/AB (ARM926EJ-S)", |
| 383 | .init = vab_init, |
| 384 | .use_scsi = 1, |
pbrook | 1640695 | 2006-04-27 23:15:07 +0000 | [diff] [blame] | 385 | }; |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 386 | |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 387 | static void versatile_machine_init(void) |
| 388 | { |
| 389 | qemu_register_machine(&versatilepb_machine); |
| 390 | qemu_register_machine(&versatileab_machine); |
| 391 | } |
| 392 | |
| 393 | machine_init(versatile_machine_init); |
| 394 | |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 395 | static void vpb_sic_class_init(ObjectClass *klass, void *data) |
| 396 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 397 | DeviceClass *dc = DEVICE_CLASS(klass); |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 398 | SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |
| 399 | |
| 400 | k->init = vpb_sic_init; |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 401 | dc->no_user = 1; |
| 402 | dc->vmsd = &vmstate_vpb_sic; |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 403 | } |
| 404 | |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 405 | static TypeInfo vpb_sic_info = { |
| 406 | .name = "versatilepb_sic", |
| 407 | .parent = TYPE_SYS_BUS_DEVICE, |
| 408 | .instance_size = sizeof(vpb_sic_state), |
| 409 | .class_init = vpb_sic_class_init, |
Peter Maydell | a796d0a | 2010-12-23 17:19:52 +0000 | [diff] [blame] | 410 | }; |
| 411 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 412 | static void versatilepb_register_types(void) |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 413 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 414 | type_register_static(&vpb_sic_info); |
Paul Brook | 3950f18 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 415 | } |
| 416 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 417 | type_init(versatilepb_register_types) |