2
0

highbank.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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-common.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 "sysemu/kvm.h"
  28. #include "sysemu/runstate.h"
  29. #include "sysemu/sysemu.h"
  30. #include "hw/boards.h"
  31. #include "exec/address-spaces.h"
  32. #include "qemu/error-report.h"
  33. #include "hw/char/pl011.h"
  34. #include "hw/ide/ahci.h"
  35. #include "hw/cpu/a9mpcore.h"
  36. #include "hw/cpu/a15mpcore.h"
  37. #include "qemu/log.h"
  38. #define SMP_BOOT_ADDR 0x100
  39. #define SMP_BOOT_REG 0x40
  40. #define MPCORE_PERIPHBASE 0xfff10000
  41. #define MVBAR_ADDR 0x200
  42. #define BOARD_SETUP_ADDR (MVBAR_ADDR + 8 * sizeof(uint32_t))
  43. #define NIRQ_GIC 160
  44. /* Board init. */
  45. static void hb_write_board_setup(ARMCPU *cpu,
  46. const struct arm_boot_info *info)
  47. {
  48. arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
  49. }
  50. static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
  51. {
  52. int n;
  53. uint32_t smpboot[] = {
  54. 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
  55. 0xe210000f, /* ands r0, r0, #0x0f */
  56. 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
  57. 0xe0830200, /* add r0, r3, r0, lsl #4 */
  58. 0xe59f2024, /* ldr r2, privbase */
  59. 0xe3a01001, /* mov r1, #1 */
  60. 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
  61. 0xe3a010ff, /* mov r1, #0xff */
  62. 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
  63. 0xf57ff04f, /* dsb */
  64. 0xe320f003, /* wfi */
  65. 0xe5901000, /* ldr r1, [r0] */
  66. 0xe1110001, /* tst r1, r1 */
  67. 0x0afffffb, /* beq <wfi> */
  68. 0xe12fff11, /* bx r1 */
  69. MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */
  70. };
  71. for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
  72. smpboot[n] = tswap32(smpboot[n]);
  73. }
  74. rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
  75. arm_boot_address_space(cpu, info));
  76. }
  77. static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
  78. {
  79. CPUARMState *env = &cpu->env;
  80. switch (info->nb_cpus) {
  81. case 4:
  82. address_space_stl_notdirty(&address_space_memory,
  83. SMP_BOOT_REG + 0x30, 0,
  84. MEMTXATTRS_UNSPECIFIED, NULL);
  85. case 3:
  86. address_space_stl_notdirty(&address_space_memory,
  87. SMP_BOOT_REG + 0x20, 0,
  88. MEMTXATTRS_UNSPECIFIED, NULL);
  89. case 2:
  90. address_space_stl_notdirty(&address_space_memory,
  91. SMP_BOOT_REG + 0x10, 0,
  92. MEMTXATTRS_UNSPECIFIED, NULL);
  93. env->regs[15] = SMP_BOOT_ADDR;
  94. break;
  95. default:
  96. break;
  97. }
  98. }
  99. #define NUM_REGS 0x200
  100. static void hb_regs_write(void *opaque, hwaddr offset,
  101. uint64_t value, unsigned size)
  102. {
  103. uint32_t *regs = opaque;
  104. if (offset == 0xf00) {
  105. if (value == 1 || value == 2) {
  106. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  107. } else if (value == 3) {
  108. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  109. }
  110. }
  111. if (offset / 4 >= NUM_REGS) {
  112. qemu_log_mask(LOG_GUEST_ERROR,
  113. "highbank: bad write offset 0x%" HWADDR_PRIx "\n", offset);
  114. return;
  115. }
  116. regs[offset / 4] = value;
  117. }
  118. static uint64_t hb_regs_read(void *opaque, hwaddr offset,
  119. unsigned size)
  120. {
  121. uint32_t value;
  122. uint32_t *regs = opaque;
  123. if (offset / 4 >= NUM_REGS) {
  124. qemu_log_mask(LOG_GUEST_ERROR,
  125. "highbank: bad read offset 0x%" HWADDR_PRIx "\n", offset);
  126. return 0;
  127. }
  128. value = regs[offset / 4];
  129. if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
  130. value |= 0x30000000;
  131. }
  132. return value;
  133. }
  134. static const MemoryRegionOps hb_mem_ops = {
  135. .read = hb_regs_read,
  136. .write = hb_regs_write,
  137. .endianness = DEVICE_NATIVE_ENDIAN,
  138. };
  139. #define TYPE_HIGHBANK_REGISTERS "highbank-regs"
  140. #define HIGHBANK_REGISTERS(obj) \
  141. OBJECT_CHECK(HighbankRegsState, (obj), TYPE_HIGHBANK_REGISTERS)
  142. typedef struct {
  143. /*< private >*/
  144. SysBusDevice parent_obj;
  145. /*< public >*/
  146. MemoryRegion iomem;
  147. uint32_t regs[NUM_REGS];
  148. } HighbankRegsState;
  149. static VMStateDescription vmstate_highbank_regs = {
  150. .name = "highbank-regs",
  151. .version_id = 0,
  152. .minimum_version_id = 0,
  153. .fields = (VMStateField[]) {
  154. VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
  155. VMSTATE_END_OF_LIST(),
  156. },
  157. };
  158. static void highbank_regs_reset(DeviceState *dev)
  159. {
  160. HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
  161. s->regs[0x40] = 0x05F20121;
  162. s->regs[0x41] = 0x2;
  163. s->regs[0x42] = 0x05F30121;
  164. s->regs[0x43] = 0x05F40121;
  165. }
  166. static void highbank_regs_init(Object *obj)
  167. {
  168. HighbankRegsState *s = HIGHBANK_REGISTERS(obj);
  169. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  170. memory_region_init_io(&s->iomem, obj, &hb_mem_ops, s->regs,
  171. "highbank_regs", 0x1000);
  172. sysbus_init_mmio(dev, &s->iomem);
  173. }
  174. static void highbank_regs_class_init(ObjectClass *klass, void *data)
  175. {
  176. DeviceClass *dc = DEVICE_CLASS(klass);
  177. dc->desc = "Calxeda Highbank registers";
  178. dc->vmsd = &vmstate_highbank_regs;
  179. dc->reset = highbank_regs_reset;
  180. }
  181. static const TypeInfo highbank_regs_info = {
  182. .name = TYPE_HIGHBANK_REGISTERS,
  183. .parent = TYPE_SYS_BUS_DEVICE,
  184. .instance_size = sizeof(HighbankRegsState),
  185. .instance_init = highbank_regs_init,
  186. .class_init = highbank_regs_class_init,
  187. };
  188. static void highbank_regs_register_types(void)
  189. {
  190. type_register_static(&highbank_regs_info);
  191. }
  192. type_init(highbank_regs_register_types)
  193. static struct arm_boot_info highbank_binfo;
  194. enum cxmachines {
  195. CALXEDA_HIGHBANK,
  196. CALXEDA_MIDWAY,
  197. };
  198. /* ram_size must be set to match the upper bound of memory in the
  199. * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
  200. * normally 0xff900000 or -m 4089. When running this board on a
  201. * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
  202. * device tree and pass -m 2047 to QEMU.
  203. */
  204. static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
  205. {
  206. DeviceState *dev = NULL;
  207. SysBusDevice *busdev;
  208. qemu_irq pic[128];
  209. int n;
  210. unsigned int smp_cpus = machine->smp.cpus;
  211. qemu_irq cpu_irq[4];
  212. qemu_irq cpu_fiq[4];
  213. qemu_irq cpu_virq[4];
  214. qemu_irq cpu_vfiq[4];
  215. MemoryRegion *sysram;
  216. MemoryRegion *sysmem;
  217. char *sysboot_filename;
  218. switch (machine_id) {
  219. case CALXEDA_HIGHBANK:
  220. machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
  221. break;
  222. case CALXEDA_MIDWAY:
  223. machine->cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
  224. break;
  225. default:
  226. assert(0);
  227. }
  228. for (n = 0; n < smp_cpus; n++) {
  229. Object *cpuobj;
  230. ARMCPU *cpu;
  231. cpuobj = object_new(machine->cpu_type);
  232. cpu = ARM_CPU(cpuobj);
  233. object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
  234. &error_abort);
  235. if (n) {
  236. /* Secondary CPUs start in PSCI powered-down state */
  237. object_property_set_bool(cpuobj, "start-powered-off", true,
  238. &error_abort);
  239. }
  240. if (object_property_find(cpuobj, "reset-cbar", NULL)) {
  241. object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
  242. &error_abort);
  243. }
  244. qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
  245. cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
  246. cpu_fiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ);
  247. cpu_virq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VIRQ);
  248. cpu_vfiq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_VFIQ);
  249. }
  250. sysmem = get_system_memory();
  251. /* SDRAM at address zero. */
  252. memory_region_add_subregion(sysmem, 0, machine->ram);
  253. sysram = g_new(MemoryRegion, 1);
  254. memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000,
  255. &error_fatal);
  256. memory_region_add_subregion(sysmem, 0xfff88000, sysram);
  257. if (bios_name != NULL) {
  258. sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
  259. if (sysboot_filename != NULL) {
  260. if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000) < 0) {
  261. error_report("Unable to load %s", bios_name);
  262. exit(1);
  263. }
  264. g_free(sysboot_filename);
  265. } else {
  266. error_report("Unable to find %s", bios_name);
  267. exit(1);
  268. }
  269. }
  270. switch (machine_id) {
  271. case CALXEDA_HIGHBANK:
  272. dev = qdev_new("l2x0");
  273. busdev = SYS_BUS_DEVICE(dev);
  274. sysbus_realize_and_unref(busdev, &error_fatal);
  275. sysbus_mmio_map(busdev, 0, 0xfff12000);
  276. dev = qdev_new(TYPE_A9MPCORE_PRIV);
  277. break;
  278. case CALXEDA_MIDWAY:
  279. dev = qdev_new(TYPE_A15MPCORE_PRIV);
  280. break;
  281. }
  282. qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
  283. qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
  284. busdev = SYS_BUS_DEVICE(dev);
  285. sysbus_realize_and_unref(busdev, &error_fatal);
  286. sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE);
  287. for (n = 0; n < smp_cpus; n++) {
  288. sysbus_connect_irq(busdev, n, cpu_irq[n]);
  289. sysbus_connect_irq(busdev, n + smp_cpus, cpu_fiq[n]);
  290. sysbus_connect_irq(busdev, n + 2 * smp_cpus, cpu_virq[n]);
  291. sysbus_connect_irq(busdev, n + 3 * smp_cpus, cpu_vfiq[n]);
  292. }
  293. for (n = 0; n < 128; n++) {
  294. pic[n] = qdev_get_gpio_in(dev, n);
  295. }
  296. dev = qdev_new("sp804");
  297. qdev_prop_set_uint32(dev, "freq0", 150000000);
  298. qdev_prop_set_uint32(dev, "freq1", 150000000);
  299. busdev = SYS_BUS_DEVICE(dev);
  300. sysbus_realize_and_unref(busdev, &error_fatal);
  301. sysbus_mmio_map(busdev, 0, 0xfff34000);
  302. sysbus_connect_irq(busdev, 0, pic[18]);
  303. pl011_create(0xfff36000, pic[20], serial_hd(0));
  304. dev = qdev_new(TYPE_HIGHBANK_REGISTERS);
  305. busdev = SYS_BUS_DEVICE(dev);
  306. sysbus_realize_and_unref(busdev, &error_fatal);
  307. sysbus_mmio_map(busdev, 0, 0xfff3c000);
  308. sysbus_create_simple("pl061", 0xfff30000, pic[14]);
  309. sysbus_create_simple("pl061", 0xfff31000, pic[15]);
  310. sysbus_create_simple("pl061", 0xfff32000, pic[16]);
  311. sysbus_create_simple("pl061", 0xfff33000, pic[17]);
  312. sysbus_create_simple("pl031", 0xfff35000, pic[19]);
  313. sysbus_create_simple("pl022", 0xfff39000, pic[23]);
  314. sysbus_create_simple(TYPE_SYSBUS_AHCI, 0xffe08000, pic[83]);
  315. if (nd_table[0].used) {
  316. qemu_check_nic_model(&nd_table[0], "xgmac");
  317. dev = qdev_new("xgmac");
  318. qdev_set_nic_properties(dev, &nd_table[0]);
  319. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  320. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
  321. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
  322. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
  323. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
  324. qemu_check_nic_model(&nd_table[1], "xgmac");
  325. dev = qdev_new("xgmac");
  326. qdev_set_nic_properties(dev, &nd_table[1]);
  327. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  328. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
  329. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
  330. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
  331. sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
  332. }
  333. /* TODO create and connect IDE devices for ide_drive_get() */
  334. highbank_binfo.ram_size = machine->ram_size;
  335. /* highbank requires a dtb in order to boot, and the dtb will override
  336. * the board ID. The following value is ignored, so set it to -1 to be
  337. * clear that the value is meaningless.
  338. */
  339. highbank_binfo.board_id = -1;
  340. highbank_binfo.nb_cpus = smp_cpus;
  341. highbank_binfo.loader_start = 0;
  342. highbank_binfo.write_secondary_boot = hb_write_secondary;
  343. highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
  344. if (!kvm_enabled()) {
  345. highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
  346. highbank_binfo.write_board_setup = hb_write_board_setup;
  347. highbank_binfo.secure_board_setup = true;
  348. } else {
  349. warn_report("cannot load built-in Monitor support "
  350. "if KVM is enabled. Some guests (such as Linux) "
  351. "may not boot.");
  352. }
  353. arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
  354. }
  355. static void highbank_init(MachineState *machine)
  356. {
  357. calxeda_init(machine, CALXEDA_HIGHBANK);
  358. }
  359. static void midway_init(MachineState *machine)
  360. {
  361. calxeda_init(machine, CALXEDA_MIDWAY);
  362. }
  363. static void highbank_class_init(ObjectClass *oc, void *data)
  364. {
  365. MachineClass *mc = MACHINE_CLASS(oc);
  366. mc->desc = "Calxeda Highbank (ECX-1000)";
  367. mc->init = highbank_init;
  368. mc->block_default_type = IF_IDE;
  369. mc->units_per_default_bus = 1;
  370. mc->max_cpus = 4;
  371. mc->ignore_memory_transaction_failures = true;
  372. mc->default_ram_id = "highbank.dram";
  373. }
  374. static const TypeInfo highbank_type = {
  375. .name = MACHINE_TYPE_NAME("highbank"),
  376. .parent = TYPE_MACHINE,
  377. .class_init = highbank_class_init,
  378. };
  379. static void midway_class_init(ObjectClass *oc, void *data)
  380. {
  381. MachineClass *mc = MACHINE_CLASS(oc);
  382. mc->desc = "Calxeda Midway (ECX-2000)";
  383. mc->init = midway_init;
  384. mc->block_default_type = IF_IDE;
  385. mc->units_per_default_bus = 1;
  386. mc->max_cpus = 4;
  387. mc->ignore_memory_transaction_failures = true;
  388. mc->default_ram_id = "highbank.dram";
  389. }
  390. static const TypeInfo midway_type = {
  391. .name = MACHINE_TYPE_NAME("midway"),
  392. .parent = TYPE_MACHINE,
  393. .class_init = midway_class_init,
  394. };
  395. static void calxeda_machines_init(void)
  396. {
  397. type_register_static(&highbank_type);
  398. type_register_static(&midway_type);
  399. }
  400. type_init(calxeda_machines_init)