2
0

highbank.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * Calxeda Highbank SoC emulation
  3. *
  4. * Copyright (c) 2010-2012 Calxeda
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2 or later, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/datadir.h"
  21. #include "qapi/error.h"
  22. #include "hw/sysbus.h"
  23. #include "migration/vmstate.h"
  24. #include "hw/arm/boot.h"
  25. #include "hw/loader.h"
  26. #include "net/net.h"
  27. #include "system/runstate.h"
  28. #include "system/system.h"
  29. #include "hw/boards.h"
  30. #include "qemu/error-report.h"
  31. #include "hw/char/pl011.h"
  32. #include "hw/ide/ahci-sysbus.h"
  33. #include "hw/cpu/a9mpcore.h"
  34. #include "hw/cpu/a15mpcore.h"
  35. #include "qemu/log.h"
  36. #include "qom/object.h"
  37. #include "cpu.h"
  38. #include "target/arm/cpu-qom.h"
  39. #define SMP_BOOT_ADDR 0x100
  40. #define SMP_BOOT_REG 0x40
  41. #define MPCORE_PERIPHBASE 0xfff10000
  42. #define MVBAR_ADDR 0x200
  43. #define BOARD_SETUP_ADDR (MVBAR_ADDR + 8 * sizeof(uint32_t))
  44. #define GIC_EXT_IRQS 128 /* EnergyCore ECX-1000 & ECX-2000 */
  45. /* Board init. */
  46. #define NUM_REGS 0x200
  47. static void hb_regs_write(void *opaque, hwaddr offset,
  48. uint64_t value, unsigned size)
  49. {
  50. uint32_t *regs = opaque;
  51. if (offset == 0xf00) {
  52. if (value == 1 || value == 2) {
  53. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  54. } else if (value == 3) {
  55. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  56. }
  57. }
  58. if (offset / 4 >= NUM_REGS) {
  59. qemu_log_mask(LOG_GUEST_ERROR,
  60. "highbank: bad write offset 0x%" HWADDR_PRIx "\n", offset);
  61. return;
  62. }
  63. regs[offset / 4] = value;
  64. }
  65. static uint64_t hb_regs_read(void *opaque, hwaddr offset,
  66. unsigned size)
  67. {
  68. uint32_t value;
  69. uint32_t *regs = opaque;
  70. if (offset / 4 >= NUM_REGS) {
  71. qemu_log_mask(LOG_GUEST_ERROR,
  72. "highbank: bad read offset 0x%" HWADDR_PRIx "\n", offset);
  73. return 0;
  74. }
  75. value = regs[offset / 4];
  76. if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
  77. value |= 0x30000000;
  78. }
  79. return value;
  80. }
  81. static const MemoryRegionOps hb_mem_ops = {
  82. .read = hb_regs_read,
  83. .write = hb_regs_write,
  84. .endianness = DEVICE_NATIVE_ENDIAN,
  85. };
  86. #define TYPE_HIGHBANK_REGISTERS "highbank-regs"
  87. OBJECT_DECLARE_SIMPLE_TYPE(HighbankRegsState, HIGHBANK_REGISTERS)
  88. struct HighbankRegsState {
  89. /*< private >*/
  90. SysBusDevice parent_obj;
  91. /*< public >*/
  92. MemoryRegion iomem;
  93. uint32_t regs[NUM_REGS];
  94. };
  95. static const VMStateDescription vmstate_highbank_regs = {
  96. .name = "highbank-regs",
  97. .version_id = 0,
  98. .minimum_version_id = 0,
  99. .fields = (const VMStateField[]) {
  100. VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
  101. VMSTATE_END_OF_LIST(),
  102. },
  103. };
  104. static void highbank_regs_reset(DeviceState *dev)
  105. {
  106. HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
  107. s->regs[0x40] = 0x05F20121;
  108. s->regs[0x41] = 0x2;
  109. s->regs[0x42] = 0x05F30121;
  110. s->regs[0x43] = 0x05F40121;
  111. }
  112. static void highbank_regs_init(Object *obj)
  113. {
  114. HighbankRegsState *s = HIGHBANK_REGISTERS(obj);
  115. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  116. memory_region_init_io(&s->iomem, obj, &hb_mem_ops, s->regs,
  117. "highbank_regs", 0x1000);
  118. sysbus_init_mmio(dev, &s->iomem);
  119. }
  120. static void highbank_regs_class_init(ObjectClass *klass, void *data)
  121. {
  122. DeviceClass *dc = DEVICE_CLASS(klass);
  123. dc->desc = "Calxeda Highbank registers";
  124. dc->vmsd = &vmstate_highbank_regs;
  125. device_class_set_legacy_reset(dc, highbank_regs_reset);
  126. }
  127. static const TypeInfo highbank_regs_info = {
  128. .name = TYPE_HIGHBANK_REGISTERS,
  129. .parent = TYPE_SYS_BUS_DEVICE,
  130. .instance_size = sizeof(HighbankRegsState),
  131. .instance_init = highbank_regs_init,
  132. .class_init = highbank_regs_class_init,
  133. };
  134. static void highbank_regs_register_types(void)
  135. {
  136. type_register_static(&highbank_regs_info);
  137. }
  138. type_init(highbank_regs_register_types)
  139. static struct arm_boot_info highbank_binfo;
  140. enum cxmachines {
  141. CALXEDA_HIGHBANK,
  142. CALXEDA_MIDWAY,
  143. };
  144. /* ram_size must be set to match the upper bound of memory in the
  145. * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
  146. * normally 0xff900000 or -m 4089. When running this board on a
  147. * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
  148. * device tree and pass -m 2047 to QEMU.
  149. */
  150. static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
  151. {
  152. DeviceState *dev = NULL;
  153. SysBusDevice *busdev;
  154. qemu_irq pic[GIC_EXT_IRQS];
  155. int n;
  156. unsigned int smp_cpus = machine->smp.cpus;
  157. qemu_irq cpu_irq[4];
  158. qemu_irq cpu_fiq[4];
  159. qemu_irq cpu_virq[4];
  160. qemu_irq cpu_vfiq[4];
  161. MemoryRegion *sysram;
  162. MemoryRegion *sysmem;
  163. char *sysboot_filename;
  164. switch (machine_id) {
  165. case CALXEDA_HIGHBANK:
  166. machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
  167. break;
  168. case CALXEDA_MIDWAY:
  169. machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
  170. break;
  171. default:
  172. g_assert_not_reached();
  173. }
  174. for (n = 0; n < smp_cpus; n++) {
  175. Object *cpuobj;
  176. ARMCPU *cpu;
  177. cpuobj = object_new(machine->cpu_type);
  178. cpu = ARM_CPU(cpuobj);
  179. object_property_add_child(OBJECT(machine), "cpu[*]", cpuobj);
  180. object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
  181. &error_abort);
  182. if (object_property_find(cpuobj, "reset-cbar")) {
  183. object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
  184. &error_abort);
  185. }
  186. qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
  187. cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
  188. cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ);
  189. cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ);
  190. cpu_vfiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VFIQ);
  191. }
  192. sysmem = get_system_memory();
  193. /* SDRAM at address zero. */
  194. memory_region_add_subregion(sysmem, 0, machine->ram);
  195. sysram = g_new(MemoryRegion, 1);
  196. memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000,
  197. &error_fatal);
  198. memory_region_add_subregion(sysmem, 0xfff88000, sysram);
  199. if (machine->firmware != NULL) {
  200. sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
  201. if (sysboot_filename != NULL) {
  202. if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000) < 0) {
  203. error_report("Unable to load %s", machine->firmware);
  204. exit(1);
  205. }
  206. g_free(sysboot_filename);
  207. } else {
  208. error_report("Unable to find %s", machine->firmware);
  209. exit(1);
  210. }
  211. }
  212. switch (machine_id) {
  213. case CALXEDA_HIGHBANK:
  214. dev = qdev_new("l2x0");
  215. busdev = SYS_BUS_DEVICE(dev);
  216. sysbus_realize_and_unref(busdev, &error_fatal);
  217. sysbus_mmio_map(busdev, 0, 0xfff12000);
  218. dev = qdev_new(TYPE_A9MPCORE_PRIV);
  219. break;
  220. case CALXEDA_MIDWAY:
  221. dev = qdev_new(TYPE_A15MPCORE_PRIV);
  222. break;
  223. }
  224. qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
  225. qdev_prop_set_uint32(dev, "num-irq", GIC_EXT_IRQS + GIC_INTERNAL);
  226. busdev = SYS_BUS_DEVICE(dev);
  227. sysbus_realize_and_unref(busdev, &error_fatal);
  228. sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
  229. for (n = 0; n < smp_cpus; n++) {
  230. sysbus_connect_irq(busdev, n, cpu_irq[n]);
  231. sysbus_connect_irq(busdev, n + smp_cpus, cpu_fiq[n]);
  232. sysbus_connect_irq(busdev, n + 2 * smp_cpus, cpu_virq[n]);
  233. sysbus_connect_irq(busdev, n + 3 * smp_cpus, cpu_vfiq[n]);
  234. }
  235. for (n = 0; n < GIC_EXT_IRQS; n++) {
  236. pic[n] = qdev_get_gpio_in(dev, n);
  237. }
  238. dev = qdev_new("sp804");
  239. qdev_prop_set_uint32(dev, "freq0", 150000000);
  240. qdev_prop_set_uint32(dev, "freq1", 150000000);
  241. busdev = SYS_BUS_DEVICE(dev);
  242. sysbus_realize_and_unref(busdev, &error_fatal);
  243. sysbus_mmio_map(busdev, 0, 0xfff34000);
  244. sysbus_connect_irq(busdev, 0, pic[18]);
  245. pl011_create(0xfff36000, pic[20], serial_hd(0));
  246. dev = qdev_new(TYPE_HIGHBANK_REGISTERS);
  247. busdev = SYS_BUS_DEVICE(dev);
  248. sysbus_realize_and_unref(busdev, &error_fatal);
  249. sysbus_mmio_map(busdev, 0, 0xfff3c000);
  250. sysbus_create_simple("pl061", 0xfff30000, pic[14]);
  251. sysbus_create_simple("pl061", 0xfff31000, pic[15]);
  252. sysbus_create_simple("pl061", 0xfff32000, pic[16]);
  253. sysbus_create_simple("pl061", 0xfff33000, pic[17]);
  254. sysbus_create_simple("pl031", 0xfff35000, pic[19]);
  255. sysbus_create_simple("pl022", 0xfff39000, pic[23]);
  256. sysbus_create_simple(TYPE_SYSBUS_AHCI, 0xffe08000, pic[83]);
  257. dev = qemu_create_nic_device("xgmac", true, NULL);
  258. if (dev) {
  259. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  260. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
  261. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
  262. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
  263. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
  264. }
  265. dev = qemu_create_nic_device("xgmac", true, NULL);
  266. if (dev) {
  267. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  268. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
  269. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
  270. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
  271. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
  272. }
  273. /* TODO create and connect IDE devices for ide_drive_get() */
  274. highbank_binfo.ram_size = machine->ram_size;
  275. /* highbank requires a dtb in order to boot, and the dtb will override
  276. * the board ID. The following value is ignored, so set it to -1 to be
  277. * clear that the value is meaningless.
  278. */
  279. highbank_binfo.board_id = -1;
  280. highbank_binfo.loader_start = 0;
  281. highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
  282. highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
  283. arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
  284. }
  285. static void highbank_init(MachineState *machine)
  286. {
  287. calxeda_init(machine, CALXEDA_HIGHBANK);
  288. }
  289. static void midway_init(MachineState *machine)
  290. {
  291. calxeda_init(machine, CALXEDA_MIDWAY);
  292. }
  293. static void highbank_class_init(ObjectClass *oc, void *data)
  294. {
  295. static const char * const valid_cpu_types[] = {
  296. ARM_CPU_TYPE_NAME("cortex-a9"),
  297. NULL
  298. };
  299. MachineClass *mc = MACHINE_CLASS(oc);
  300. mc->desc = "Calxeda Highbank (ECX-1000)";
  301. mc->init = highbank_init;
  302. mc->valid_cpu_types = valid_cpu_types;
  303. mc->block_default_type = IF_IDE;
  304. mc->units_per_default_bus = 1;
  305. mc->max_cpus = 4;
  306. mc->ignore_memory_transaction_failures = true;
  307. mc->default_ram_id = "highbank.dram";
  308. }
  309. static const TypeInfo highbank_type = {
  310. .name = MACHINE_TYPE_NAME("highbank"),
  311. .parent = TYPE_MACHINE,
  312. .class_init = highbank_class_init,
  313. };
  314. static void midway_class_init(ObjectClass *oc, void *data)
  315. {
  316. static const char * const valid_cpu_types[] = {
  317. ARM_CPU_TYPE_NAME("cortex-a15"),
  318. NULL
  319. };
  320. MachineClass *mc = MACHINE_CLASS(oc);
  321. mc->desc = "Calxeda Midway (ECX-2000)";
  322. mc->init = midway_init;
  323. mc->valid_cpu_types = valid_cpu_types;
  324. mc->block_default_type = IF_IDE;
  325. mc->units_per_default_bus = 1;
  326. mc->max_cpus = 4;
  327. mc->ignore_memory_transaction_failures = true;
  328. mc->default_ram_id = "highbank.dram";
  329. }
  330. static const TypeInfo midway_type = {
  331. .name = MACHINE_TYPE_NAME("midway"),
  332. .parent = TYPE_MACHINE,
  333. .class_init = midway_class_init,
  334. };
  335. static void calxeda_machines_init(void)
  336. {
  337. type_register_static(&highbank_type);
  338. type_register_static(&midway_type);
  339. }
  340. type_init(calxeda_machines_init)